diff --git a/knode/knarticlefactory.cpp b/knode/knarticlefactory.cpp index e3bb9c7e32..3b550292da 100644 --- a/knode/knarticlefactory.cpp +++ b/knode/knarticlefactory.cpp @@ -1,1036 +1,1036 @@ /* knarticlefactory.cpp KNode, the KDE newsreader Copyright (c) 1999-2000 the KNode authors. See file AUTHORS for details This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, US */ #include #include #include #include #include #include #include #include #include "knarticlefactory.h" #include "knglobals.h" #include "knconfigmanager.h" #include "kngroupmanager.h" #include "knaccountmanager.h" #include "kngroup.h" #include "knfoldermanager.h" #include "knfolder.h" #include "kncomposer.h" #include "knnntpaccount.h" #include "knlistbox.h" #include "utilities.h" #include "resource.h" KNArticleFactory::KNArticleFactory(KNFolderManager *fm, KNGroupManager *gm, QObject *p, const char *n) : QObject(p, n), KNJobConsumer(), f_olManager(fm), g_rpManager(gm), s_endErrDlg(0) { c_ompList.setAutoDelete(true); } KNArticleFactory::~KNArticleFactory() { delete s_endErrDlg; } void KNArticleFactory::createPosting(KNNntpAccount *a) { if(!a) return; QString sig; KNLocalArticle *art=newArticle(0, sig, knGlobals.cfgManager->postNewsTechnical()->charset()); if(!art) return; art->setServerId(a->id()); art->setDoPost(true); art->setDoMail(false); KNComposer *c=new KNComposer(art, QString::null, sig, QString::null, true); c_ompList.append(c); connect(c, SIGNAL(composerDone(KNComposer*)), this, SLOT(slotComposerDone(KNComposer*))); c->show(); } void KNArticleFactory::createPosting(KNGroup *g) { if(!g) return; QCString chset; if (g->useCharset()) chset = g->defaultCharset(); else chset = knGlobals.cfgManager->postNewsTechnical()->charset(); QString sig; KNLocalArticle *art=newArticle(g, sig, chset); if(!art) return; art->setServerId(g->account()->id()); art->setDoPost(true); art->setDoMail(false); art->newsgroups()->fromUnicodeString(g->groupname(), art->defaultCharset()); KNComposer *c=new KNComposer(art, QString::null, sig, QString::null, true); c_ompList.append(c); connect(c, SIGNAL(composerDone(KNComposer*)), this, SLOT(slotComposerDone(KNComposer*))); c->show(); } void KNArticleFactory::createReply(KNRemoteArticle *a, QString selectedText, bool post, bool mail) { if(!a) return; KNGroup *g=static_cast(a->collection()); QCString chset; if (knGlobals.cfgManager->postNewsTechnical()->useOwnCharset()) { if (g->useCharset()) chset = g->defaultCharset(); else chset = knGlobals.cfgManager->postNewsTechnical()->charset(); } else chset = a->contentType()->charset(); //create new article QString sig; KNLocalArticle *art=newArticle(g, sig, chset); if(!art) return; art->setServerId(g->account()->id()); art->setDoPost(post); art->setDoMail(mail); //------------------------- ---------------------------- //subject QString subject=a->subject()->asUnicodeString(); if(subject.left(3).upper()!="RE:") subject.prepend("Re: "); art->subject()->fromUnicodeString(subject, a->subject()->rfc2047Charset()); //newsgroups KNHeaders::FollowUpTo *fup2=a->followUpTo(false); if(fup2 && !fup2->isEmpty()) { if(fup2->as7BitString(false).upper()=="POSTER") { //Followup-To: poster if (post) // warn the user KMessageBox::information(knGlobals.topWidget,i18n("The author has requested a reply by e-mail instead\nof a followup to the newsgroup (Followup-To: poster)"), QString::null,"followupToPosterWarning"); art->setDoPost(false); art->setDoMail(true); } else art->newsgroups()->from7BitString(fup2->as7BitString(false), art->defaultCharset(), false); } else art->newsgroups()->from7BitString(a->newsgroups()->as7BitString(false), art->defaultCharset(), false); //To KNHeaders::ReplyTo *replyTo=a->replyTo(false); KNHeaders::AddressField address; if(replyTo && !replyTo->isEmpty()) { if(replyTo->hasName()) address.setName(replyTo->name()); if(replyTo->hasEmail()) address.setEmail(replyTo->email().copy()); } else { KNHeaders::From *from=a->from(); if(from->hasName()) address.setName(from->name()); if(from->hasEmail()) address.setEmail(from->email().copy()); } art->to()->addAddress(address); //References KNHeaders::References *references=a->references(false); QCString refs; if(references && !references->isEmpty()) refs=references->as7BitString(false).copy()+" "+a->messageID()->as7BitString(false); else refs=a->messageID()->as7BitString(false).copy(); art->references()->from7BitString(refs, art->defaultCharset(),false); //------------------------- --------------------------- //--------------------------- ----------------------------- // attribution line QString attribution=knGlobals.cfgManager->postNewsComposer()->intro(); QString name(a->from()->name()); if (name.isEmpty()) name = QString::fromLatin1(a->from()->email()); attribution.replace(QRegExp("%NAME"),name); attribution.replace(QRegExp("%EMAIL"),QString::fromLatin1(a->from()->email())); attribution.replace(QRegExp("%DATE"),KGlobal::locale()->formatDateTime(a->date()->qdt(),false)); attribution.replace(QRegExp("%MSID"),a->messageID()->asUnicodeString()); attribution+="\n\n"; QString quoted=attribution; QString notRewraped=QString::null; QStringList text; QStringList::Iterator line; bool incSig=knGlobals.cfgManager->postNewsComposer()->includeSignature(); if (selectedText.isEmpty()) a->decodedText(text); else text = QStringList::split('\n',selectedText); for(line=text.begin(); line!=text.end(); ++line) { if(!incSig && (*line)=="-- ") break; if ((*line)[0]=='>') quoted+=">"+(*line)+"\n"; // second quote level without space else quoted+="> "+(*line)+"\n"; } if(knGlobals.cfgManager->postNewsComposer()->rewrap()) { //rewrap original article notRewraped=quoted; // store the original text in here, the user can request it in the composer quoted=attribution; quoted += rewrapStringList(text, knGlobals.cfgManager->postNewsComposer()->maxLineLength(), '>', !incSig, false); } //-------------------------- ----------------------------- //open composer KNComposer *c=new KNComposer(art, quoted, sig, notRewraped, true); c_ompList.append(c); connect(c, SIGNAL(composerDone(KNComposer*)), this, SLOT(slotComposerDone(KNComposer*))); c->show(); } void KNArticleFactory::createForward(KNArticle *a) { if(!a) return; QCString chset; if (knGlobals.cfgManager->postNewsTechnical()->useOwnCharset()) chset = knGlobals.cfgManager->postNewsTechnical()->charset(); else chset = a->contentType()->charset(); //create new article QString sig; KNLocalArticle *art=newArticle(0, sig, chset); if(!art) return; art->setDoPost(false); art->setDoMail(true); //------------------------- ---------------------------- //subject QString subject=("Fwd: "+a->subject()->asUnicodeString()); art->subject()->fromUnicodeString(subject, a->subject()->rfc2047Charset()); //------------------------- --------------------------- //--------------------------- ----------------------------- QString fwd=QString("\n,-------------- %1\n\n").arg(i18n("Forwarded message (begin)")); fwd+=( i18n("Subject")+": "+a->subject()->asUnicodeString()+"\n"); fwd+=( i18n("From")+": "+a->from()->asUnicodeString()+"\n"); fwd+=( i18n("Date")+": "+a->date()->asUnicodeString()+"\n\n"); KNMimeContent *text=a->textContent(); if(text) { QString decoded; text->decodedText(decoded); fwd+=decoded; } fwd+=QString("\n`-------------- %1\n").arg(i18n("Forwarded message (end)")); //--------------------------- ---------------------------- //open composer KNComposer *c=new KNComposer(art, fwd, sig, QString::null, true); c_ompList.append(c); connect(c, SIGNAL(composerDone(KNComposer*)), this, SLOT(slotComposerDone(KNComposer*))); c->show(); } void KNArticleFactory::createCancel(KNArticle *a) { if(!cancelAllowed(a)) return; if(KMessageBox::No==KMessageBox::questionYesNo(knGlobals.topWidget, i18n("Do you really want to cancel this article?"))) return; bool sendNow; switch (KMessageBox::warningYesNoCancel(knGlobals.topWidget, i18n("Do you want to send the cancel\nmessage now or later?"), i18n("Question"),i18n("&Now"),i18n("&Later"))) { case KMessageBox::Yes : sendNow = true; break; case KMessageBox::No : sendNow = false; break; default : return; } KNGroup *grp; KNNntpAccount *nntp; if(a->type()==KNMimeBase::ATremote) nntp=(static_cast(a->collection()))->account(); else { KNLocalArticle *la=static_cast(a); la->setCanceled(true); la->updateListItem(); nntp=knGlobals.accManager->account(la->serverId()); if(!nntp) nntp=knGlobals.accManager->first(); if(!nntp) { KMessageBox::error(knGlobals.topWidget, i18n("You have no valid news-account configured!")); return; } } grp=knGlobals.grpManager->group(a->newsgroups()->firstGroup(), nntp); QString sig; KNLocalArticle *art=newArticle(grp, sig, "us-ascii", false); if(!art) return; //init art->setDoPost(true); art->setDoMail(false); //server art->setServerId(nntp->id()); //subject KNHeaders::MessageID *msgId=a->messageID(); QCString tmp; tmp="cancel of "+msgId->as7BitString(false); art->subject()->from7BitString(tmp, art->defaultCharset(), false); //newsgroups art->newsgroups()->from7BitString(a->newsgroups()->as7BitString(false), art->defaultCharset(), false); //control tmp="cancel "+msgId->as7BitString(false); art->control()->from7BitString(tmp, art->defaultCharset(), false); //Lines art->lines()->setNumberOfLines(1); //body art->fromUnicodeString(QString::fromLatin1("cancel by original author\n")); //assemble art->assemble(); //send KNLocalArticle::List lst; lst.append(art); sendArticles(&lst, sendNow); } void KNArticleFactory::createSupersede(KNArticle *a) { if (!a) return; if(!cancelAllowed(a)) return; if(KMessageBox::No==KMessageBox::questionYesNo(knGlobals.topWidget, i18n("Do you really want to supersede this article?"))) return; KNGroup *grp; KNNntpAccount *nntp; if(a->type()==KNMimeBase::ATremote) nntp=(static_cast(a->collection()))->account(); else { KNLocalArticle *la=static_cast(a); la->setCanceled(true); la->updateListItem(); nntp=knGlobals.accManager->account(la->serverId()); if(!nntp) nntp=knGlobals.accManager->first(); if(!nntp) { KMessageBox::error(knGlobals.topWidget, i18n("You have no valid news-account configured!")); return; } } grp=knGlobals.grpManager->group(a->newsgroups()->firstGroup(), nntp); //new article QString sig; KNLocalArticle *art=newArticle(grp, sig, a->contentType()->charset()); if(!art) return; art->setDoPost(true); art->setDoMail(false); //server art->setServerId(nntp->id()); //subject art->subject()->fromUnicodeString(a->subject()->asUnicodeString(), a->subject()->rfc2047Charset()); //newsgroups art->newsgroups()->from7BitString(a->newsgroups()->as7BitString(false), art->defaultCharset(), false); //followup-to art->followUpTo()->from7BitString(a->followUpTo()->as7BitString(false), art->defaultCharset(), false); //References art->references()->from7BitString(a->references()->as7BitString(false), art->defaultCharset(), false); //Supersedes art->supersedes()->from7BitString(a->messageID()->as7BitString(false), art->defaultCharset(), false); //Body QString text; KNMimeContent *textContent=a->textContent(); if(textContent) textContent->decodedText(text); //open composer KNComposer *c=new KNComposer(art, text, sig); c_ompList.append(c); connect(c, SIGNAL(composerDone(KNComposer*)), this, SLOT(slotComposerDone(KNComposer*))); c->show(); } void KNArticleFactory::createMail(KNHeaders::AddressField *address) { //create new article QString sig; KNLocalArticle *art=newArticle(0, sig, knGlobals.cfgManager->postNewsTechnical()->charset()); if(!art) return; art->setDoMail(true); art->setDoPost(false); art->to()->addAddress((*address)); //open composer KNComposer *c=new KNComposer(art, QString::null, sig, QString::null, true); c_ompList.append(c); connect(c, SIGNAL(composerDone(KNComposer*)), this, SLOT(slotComposerDone(KNComposer*))); c->show(); } void KNArticleFactory::edit(KNLocalArticle *a) { if(!a) return; KNComposer *com=findComposer(a); if(com) { KWin::setActiveWindow(com->winId()); return; } if(a->editDisabled()) { KMessageBox::sorry(knGlobals.topWidget, i18n("This article cannot be edited.")); return; } //find signature KNConfig::Identity *id=knGlobals.cfgManager->identity(); if(a->doPost()) { KNNntpAccount *acc=knGlobals.accManager->account(a->serverId()); if(acc) { KNHeaders::Newsgroups *grps=a->newsgroups(); KNGroup *grp=g_rpManager->group(grps->firstGroup(), acc); if(grp && grp->identity() && grp->identity()->hasSignature()) id=grp->identity(); } } //open composer com=new KNComposer(a, QString::null, id->getSignature()); c_ompList.append(com); connect(com, SIGNAL(composerDone(KNComposer*)), this, SLOT(slotComposerDone(KNComposer*))); com->show(); } void KNArticleFactory::saveArticles(KNLocalArticle::List *l, KNFolder *f) { if(!f->saveArticles(l)) { displayInternalFileError(); for(KNLocalArticle *a=l->first(); a; a=l->next()) if(a->id()==-1) delete a; //ok, this is ugly - we simply delete orphant articles } } bool KNArticleFactory::deleteArticles(KNLocalArticle::List *l, bool ask) { if(l->isEmpty()) return true; if(ask) { QStringList lst; for(KNLocalArticle *a=l->first(); a; a=l->next()) { if(a->isLocked()) continue; if(a->subject()->isEmpty()) lst << i18n("no subject"); else lst << a->subject()->asUnicodeString(); } if( KMessageBox::No == KMessageBox::questionYesNoList( knGlobals.topWidget, i18n("Do you really want to delete these articles?"), lst) ) return false; } KNFolder *f=static_cast(l->first()->collection()); if(f) f->removeArticles(l, true); else { for(KNLocalArticle *a=l->first(); a; a=l->next()) delete a; } return true; } void KNArticleFactory::sendArticles(KNLocalArticle::List *l, bool now) { KNJobData *job=0; KNServerInfo *ser=0; KNLocalArticle::List unsent, sent; for(KNLocalArticle *a=l->first(); a; a=l->next()) { if(a->pending()) unsent.append(a); else sent.append(a); } if(!sent.isEmpty()) { showSendErrorDialog(); for(KNLocalArticle *a=sent.first(); a; a=sent.next()) - s_endErrDlg->append(a->subject()->asUnicodeString(), i18n("Article has been sent already")); + s_endErrDlg->append(a->subject()->asUnicodeString(), i18n("Article has already been sent.")); } if(!now) { saveArticles(&unsent, f_olManager->outbox()); return; } for(KNLocalArticle *a=unsent.first(); a; a=unsent.next()) { if(a->isLocked()) continue; if(!a->hasContent()) { KNFolder *f=static_cast(a->collection()); if(!f->loadArticle(a)) { showSendErrorDialog(); - s_endErrDlg->append(a->subject()->asUnicodeString(), i18n("Could not load article")); + s_endErrDlg->append(a->subject()->asUnicodeString(), i18n("Unable to load article!")); continue; } } if(a->doPost() && !a->posted()) { ser=knGlobals.accManager->account(a->serverId()); job=new KNJobData(KNJobData::JTpostArticle, this, ser, a); emitJob(job); } else if(a->doMail() && !a->mailed()) { ser=knGlobals.accManager->smtp(); job=new KNJobData(KNJobData::JTmail, this, ser, a); emitJob(job); } } } void KNArticleFactory::sendOutbox() { KNLocalArticle::List lst; KNFolder *ob=f_olManager->outbox(); if(!ob->loadHdrs()) { - KMessageBox::error(knGlobals.topWidget, i18n("Could not load the outbox!")); + KMessageBox::error(knGlobals.topWidget, i18n("Unable to load the outbox-folder!")); return; } for(int i=0; i< ob->length(); i++) lst.append(ob->at(i)); sendArticles(&lst, true); } bool KNArticleFactory::closeComposeWindows() { KNComposer *comp; while((comp=c_ompList.first())) if(!comp->close()) return false; return true; } void KNArticleFactory::deleteComposersForFolder(KNFolder *f) { QList list=c_ompList; for(KNComposer *i=list.first(); i; i=list.next()) for(int x=0; xcount(); x++) if(i->article()==f->at(x)) { c_ompList.removeRef(i); //auto delete continue; } } void KNArticleFactory::deleteComposerForArticle(KNLocalArticle *a) { KNComposer *com=findComposer(a); if(com) c_ompList.removeRef(com); //auto delete } KNComposer* KNArticleFactory::findComposer(KNLocalArticle *a) { for(KNComposer *i=c_ompList.first(); i; i=c_ompList.next()) if(i->article()==a) return i; return 0; } void KNArticleFactory::configChanged() { for(KNComposer *c=c_ompList.first(); c; c=c_ompList.next()) c->setConfig(false); } void KNArticleFactory::processJob(KNJobData *j) { if(j->canceled()) { delete j; return; } KNLocalArticle *art=static_cast(j->data()); KNLocalArticle::List lst; lst.append(art); if(!j->success()) { showSendErrorDialog(); s_endErrDlg->append(art->subject()->asUnicodeString(), j->errorString()); delete j; //unlock article //sending of this article failed => move it to the "Outbox-Folder" if(art->collection()!=f_olManager->outbox()) saveArticles(&lst, f_olManager->outbox()); } else { //disable edit art->setEditDisabled(true); switch(j->type()) { case KNJobData::JTpostArticle: delete j; //unlock article art->setPosted(true); if(art->doMail() && !art->mailed()) { //article has been posted, now mail it sendArticles(&lst, true); return; } break; case KNJobData::JTmail: delete j; //unlock article art->setMailed(true); break; default: break; }; //article has been sent successfully => move it to the "Sent-folder" if(!f_olManager->sent()->saveArticles(&lst)) { displayInternalFileError(); if(art->collection()==0) delete art; } } } KNLocalArticle* KNArticleFactory::newArticle(KNGroup *g, QString &sig, QCString defChset, bool withXHeaders) { KNConfig::PostNewsTechnical *pnt=knGlobals.cfgManager->postNewsTechnical(); if(pnt->generateMessageID() && pnt->hostname().isEmpty()) { KMessageBox::sorry(knGlobals.topWidget, i18n("Please set a hostname for the generation\nof the message-id or disable it.")); return 0; } KNLocalArticle *art=new KNLocalArticle(0); KNConfig::Identity *grpId=0, *defId=0, *id=0; QFont::CharSet cs=KGlobal::charsets()->charsetForEncoding(pnt->charset()); if(!g) grpId=0; else grpId=g->identity(); defId=knGlobals.cfgManager->identity(); //Message-id if(pnt->generateMessageID()) art->messageID()->generate(pnt->hostname()); //From KNHeaders::From *from=art->from(); from->setRFC2047Charset(cs); //name if(grpId && grpId->hasName()) id=grpId; else id=defId; if(id->hasName()) from->setName(id->name()); //email if(grpId && grpId->hasEmail()) id=grpId; else id=defId; if(id->hasEmail()&&id->emailIsValid()) from->setEmail(id->email().latin1()); else { KMessageBox::sorry(knGlobals.topWidget, i18n("Please enter a valid e-mail address.")); delete art; return 0; } //Reply-To if(grpId && grpId->hasReplyTo()) id=grpId; else id=defId; if(id->hasReplyTo()) art->replyTo()->fromUnicodeString(id->replyTo(), cs); //Organization if(grpId && grpId->hasOrga()) id=grpId; else id=defId; if(id->hasOrga()) art->organization()->fromUnicodeString(id->orga(), cs); //Date art->date()->setUnixTime(); //set current date+time //User-Agent if( !pnt->noUserAgent() ) { art->userAgent()->from7BitString("KNode/" KNODE_VERSION, art->defaultCharset(), false); } //Mime KNHeaders::ContentType *type=art->contentType(); type->setMimeType("text/plain"); type->setCharset(defChset); if (defChset.lower()=="us-ascii") art->contentTransferEncoding()->setCte(KNHeaders::CE7Bit); else art->contentTransferEncoding()->setCte(pnt->allow8BitBody()? KNHeaders::CE8Bit : KNHeaders::CEquPr); //X-Headers if(withXHeaders) { KNConfig::XHeaders::Iterator it; for(it=pnt->xHeaders().begin(); it!=pnt->xHeaders().end(); ++it) art->setHeader( new KNHeaders::Generic( (QCString("X-")+(*it).name()), (*it).value(), cs ) ); } //Signature if(grpId && grpId->hasSignature()) id=grpId; else id=defId; if(id->hasSignature()) sig=id->getSignature(); else sig=QString::null; return art; } bool KNArticleFactory::cancelAllowed(KNArticle *a) { if(!a) return false; if(a->type()==KNMimeBase::ATlocal) { KNLocalArticle *localArt=static_cast(a); if(localArt->doMail() && !localArt->doPost()) { KMessageBox::sorry(knGlobals.topWidget, i18n("Emails cannot be canceled or superseded!")); return false; } KNHeaders::Control *ctrl=localArt->control(false); if(ctrl && ctrl->isCancel()) { KMessageBox::sorry(knGlobals.topWidget, i18n("Cancel messages cannot be canceled or superseded!")); return false; } if(!localArt->posted()) { KMessageBox::sorry(knGlobals.topWidget, i18n("Only sent articles can be canceled or superseded!")); return false; } if(localArt->canceled()) { KMessageBox::sorry(knGlobals.topWidget, i18n("This article has already been canceled or superseded!")); return false; } KNHeaders::MessageID *mid=localArt->messageID(false); if(!mid || mid->isEmpty()) { KMessageBox::sorry(knGlobals.topWidget, i18n("This article cannot be canceled or superseded,\nbecause it's message-id has not been created by KNode!\nBut you can look for your article in the newsgroup\nand cancel (or supersede) it there.")); return false; } return true; } else if(a->type()==KNMimeBase::ATremote) { KNRemoteArticle *remArt=static_cast(a); KNGroup *g=static_cast(a->collection()); KNConfig::Identity *defId=knGlobals.cfgManager->identity(), *gid=g->identity(); bool ownArticle=true; if(gid && gid->hasName()) ownArticle=( gid->name()==remArt->from()->name() ); else ownArticle=( defId->name()==remArt->from()->name() ); if(ownArticle) { if(gid && gid->hasEmail()) ownArticle=( gid->email().latin1()==remArt->from()->email() ); else ownArticle=( defId->email().latin1()==remArt->from()->email() ); } if(!ownArticle) { KMessageBox::sorry(knGlobals.topWidget, i18n("This article does not appear to be from you.\nYou can only cancel or supersede you own articles.")); return false; } if(!remArt->hasContent()) { KMessageBox::sorry(knGlobals.topWidget, i18n("You have to download the article body\nbefore you can cancel or supersede the article.")); return false; } return true; } return false; } void KNArticleFactory::showSendErrorDialog() { if(!s_endErrDlg) { s_endErrDlg=new KNSendErrorDialog(); connect(s_endErrDlg, SIGNAL(dialogDone()), this, SLOT(slotSendErrorDialogDone())); } s_endErrDlg->show(); } void KNArticleFactory::slotComposerDone(KNComposer *com) { bool delCom=true; KNLocalArticle::List lst; lst.append(com->article()); switch(com->result()) { case KNComposer::CRsendNow: delCom=com->hasValidData(); if(delCom) { com->applyChanges(); sendArticles(&lst, true); } else com->setDoneSuccess(false); break; case KNComposer::CRsendLater: delCom=com->hasValidData(); if(delCom) { com->applyChanges(); sendArticles(&lst, false); } else com->setDoneSuccess(false); break; case KNComposer::CRsave : com->applyChanges(); saveArticles(&lst, f_olManager->drafts()); break; case KNComposer::CRdelAsk: delCom=deleteArticles(&lst, true); break; case KNComposer::CRdel: delCom=deleteArticles(&lst, false); break; case KNComposer::CRcancel: // just close... break; default: break; }; if(delCom) c_ompList.removeRef(com); //auto delete else KWin::setActiveWindow(com->winId()); } void KNArticleFactory::slotSendErrorDialogDone() { delete s_endErrDlg; s_endErrDlg=0; } //====================================================================================================== KNSendErrorDialog::KNSendErrorDialog() : QSemiModal(knGlobals.topWidget, 0, true) { p_ixmap=knGlobals.cfgManager->appearance()->icon(KNConfig::Appearance::sendErr); QVBoxLayout *topL=new QVBoxLayout(this, 5,5); QLabel *l=new QLabel(QString("%1").arg(i18n("Failed tasks:")), this); topL->addWidget(l); j_obs=new QListBox(this); topL->addWidget(j_obs, 1); e_rror=new QLabel(this); topL->addSpacing(5); topL->addWidget(e_rror); KSeparator *sep=new KSeparator(this); topL->addSpacing(10); topL->addWidget(sep); c_loseBtn=new QPushButton(i18n("&Close"), this); c_loseBtn->setDefault(true); topL->addWidget(c_loseBtn, 0, Qt::AlignRight); connect(j_obs, SIGNAL(highlighted(int)), this, SLOT(slotHighlighted(int))); connect(c_loseBtn, SIGNAL(clicked()), this, SLOT(slotCloseBtnClicked())); setCaption(kapp->makeStdCaption(i18n("Errors while sending"))); restoreWindowSize("sendDlg", this, sizeHint()); } KNSendErrorDialog::~KNSendErrorDialog() { saveWindowSize("sendDlg", size()); } void KNSendErrorDialog::append(const QString &subject, const QString &error) { LBoxItem *it=new LBoxItem(error, subject, &p_ixmap); j_obs->insertItem(it); j_obs->setCurrentItem(it); } void KNSendErrorDialog::slotHighlighted(int idx) { LBoxItem *it=static_cast(j_obs->item(idx)); if(it) { QString tmp=i18n("Error message:
")+it->error; e_rror->setText(tmp); } } void KNSendErrorDialog::slotCloseBtnClicked() { emit dialogDone(); } //------------------------------- #include "knarticlefactory.moc" diff --git a/knode/knarticlewidget.cpp b/knode/knarticlewidget.cpp index 3b48c06c28..4b5c3be22e 100644 --- a/knode/knarticlewidget.cpp +++ b/knode/knarticlewidget.cpp @@ -1,1350 +1,1350 @@ /* knarticlewidget.cpp KNode, the KDE newsreader Copyright (c) 1999-2000 the KNode authors. See file AUTHORS for details This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, US */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "resource.h" #include "knmime.h" #include "knarticlewidget.h" #include "knglobals.h" #include "knarticlemanager.h" #include "knfoldermanager.h" #include "knarticlefactory.h" #include "knconfigmanager.h" #include "kngroup.h" #include "knfolder.h" #include "knnntpaccount.h" #include "knstringsplitter.h" #include "utilities.h" #define PUP_OPEN 1000 #define PUP_SAVE 2000 #define PUP_COPYURL 3000 #define PUP_SELALL 4000 #define PUP_COPY 5000 #define HDR_COL 0 #define QCOL_1 1 #define QCOL_2 2 #define QCOL_3 3 KNArticleWidget::KNArticleWidget(KActionCollection* actColl, QWidget *parent, const char *name ) : QTextBrowser(parent, name), a_rticle(0), a_tt(0), h_tmlDone(false), a_ctions(actColl) { i_nstances.append(this); //custom tags , QStyleSheetItem *style; style=new QStyleSheetItem(styleSheet(), "bodyblock"); style->setDisplayMode(QStyleSheetItem::DisplayBlock); style->setMargin(QStyleSheetItem::MarginAll, 5); style=new QStyleSheetItem(styleSheet(), "headerblock"); style->setDisplayMode(QStyleSheetItem::DisplayBlock); style->setMargin(QStyleSheetItem::MarginLeft, 10); style->setMargin(QStyleSheetItem::MarginVertical, 2); setFocusPolicy(QWidget::WheelFocus); //popups u_rlPopup=new KPopupMenu(); u_rlPopup->insertItem(SmallIcon("fileopen"),i18n("&Open Link"), PUP_OPEN); u_rlPopup->insertItem(SmallIcon("editcopy"),i18n("&Copy Link Location"), PUP_COPYURL); a_ttPopup=new KPopupMenu(); a_ttPopup->insertItem(SmallIcon("fileopen"),i18n("&Open Attachment"), PUP_OPEN); a_ttPopup->insertItem(SmallIcon("filesave"),i18n("&Save Attachment"), PUP_SAVE); //actions a_ctSave = KStdAction::save(this, SLOT(slotSave()), a_ctions); a_ctSave->setText("&Save..."); a_ctPrint = KStdAction::print(this, SLOT(slotPrint()), a_ctions); a_ctSelAll = KStdAction::selectAll(this, SLOT(slotSelectAll()), a_ctions); a_ctCopy = KStdAction::copy(this, SLOT(copy()), a_ctions); a_ctReply = new KAction(i18n("&Followup to Newsgroup..."),"message_reply", Key_R , this, SLOT(slotReply()), a_ctions, "article_postReply"); a_ctRemail = new KAction(i18n("Reply by E-&Mail..."),"mail_reply", Key_A , this, SLOT(slotRemail()), a_ctions, "article_mailReply"); a_ctForward = new KAction(i18n("Forw&ard by E-Mail..."),"mail_forward", Key_F , this, SLOT(slotForward()), a_ctions, "article_forward"); a_ctCancel = new KAction(i18n("article","&Cancel"), 0 , this, SLOT(slotCancel()), a_ctions, "article_cancel"); a_ctSupersede = new KAction(i18n("S&upersede..."), 0 , this, SLOT(slotSupersede()), a_ctions, "article_supersede"); a_ctVerify = new KAction(i18n("&Verify PGP Signature"), 0, this, SLOT(slotVerify()), a_ctions, "article_verify"); a_ctToggleFullHdrs = new KToggleAction(i18n("Show &all headers"), "text_block", 0 , this, SLOT(slotToggleFullHdrs()), a_ctions, "view_showAllHdrs"); a_ctToggleRot13 = new KToggleAction(i18n("&Unscramble (Rot 13)"), "decrypted", 0 , this, SLOT(slotToggleRot13()), a_ctions, "view_rot13"); a_ctSetCharset = new KSelectAction(i18n("Chars&et"), 0, a_ctions, "set_charset"); QStringList cs=KGlobal::charsets()->availableEncodingNames(); cs.prepend(i18n("Automatic")); a_ctSetCharset->setItems(cs); a_ctSetCharset->setCurrentItem(0); connect(a_ctSetCharset, SIGNAL(activated(const QString&)), this, SLOT(slotSetCharset(const QString&))); overrideCS=QFont::ISO_8859_1; forceCS=false; //timer t_imer=new QTimer(this); connect(t_imer, SIGNAL(timeout()), this, SLOT(slotTimeout())); //config f_ullHdrs=false; a_ctToggleFullHdrs->setChecked(f_ullHdrs); r_ot13=false; a_ctToggleRot13->setChecked(false); applyConfig(); } KNArticleWidget::~KNArticleWidget() { i_nstances.removeRef(this); delete a_tt; delete a_ttPopup; delete u_rlPopup; } bool KNArticleWidget::scrollingDownPossible() { return ((contentsY()+visibleHeight())key()) { case Key_Prior: scrollBy( 0, -visibleHeight()+offs); break; case Key_Next: scrollBy( 0, visibleHeight()-offs); break; default: QTextBrowser::keyPressEvent(e); } } void KNArticleWidget::viewportMousePressEvent(QMouseEvent *e) { QString a=QTextBrowser::anchorAt(e->pos()); if(!a.isEmpty() && (e->button()==RightButton || e->button()==MidButton)) anchorClicked(a, e->button(), &(e->globalPos())); else if (e->button()==RightButton) b_odyPopup->popup(e->globalPos()); QTextBrowser::viewportMousePressEvent(e); } void KNArticleWidget::viewportMouseReleaseEvent(QMouseEvent *e) { QTextBrowser::viewportMouseReleaseEvent(e); if (e->button()==LeftButton) { if(hasSelectedText() && !selectedText().isEmpty()) { copy(); a_ctCopy->setEnabled(true); } else a_ctCopy->setEnabled(false); } } void KNArticleWidget::applyConfig() { KNConfig::Appearance *app=knGlobals.cfgManager->appearance(); QColorGroup pcg(paperColorGroup()); pcg.setColor(QColorGroup::Base, app->backgroundColor()); pcg.setColor(QColorGroup::Text, app->textColor()); setPaperColorGroup(pcg); setLinkColor(app->linkColor()); if(!knGlobals.cfgManager->readNewsGeneral()->autoMark()) t_imer->stop(); updateContents(); } QString KNArticleWidget::toHtmlString(const QString &line, bool parseURLs, bool beautification, bool allowRot13) { QString text,result; QRegExp regExp; uint len=line.length(); int matchLen; bool forceNBSP=false; //use " " for spaces => workaround for a bug in QTextBrowser if (allowRot13 && r_ot13) text = rot13(line); else text = line; - if (!knGlobals.cfgManager->readNewsGeneral()->interpretFormatTags()) + if (!knGlobals.cfgManager->readNewsViewer()->interpretFormatTags()) beautification=false; for(uint idx=0; idx' : result+=">"; break; case '&' : result+="&"; break; case '"' : result+="""; break; case '\t': result+="        "; break; // tab == 8 spaces case 32 : if(text[idx+1].isSpace()) { while(text[idx].isSpace()) { result+=" "; idx++; } idx--; forceNBSP=true; // force   for the rest of this line } else if(idx==0 || forceNBSP) { result+=" "; forceNBSP=true; // force   for the rest of this line } else result+=' '; break; case 'h' : if((parseURLs)&& (text[idx+1].latin1()=='t')) { // don't do all the stuff for every 'h' regExp="^https?://[^\\s<>()\"|]+"; if (regExp.match(text,idx,&matchLen)!=-1) { result+=QString::fromLatin1("") + text.mid(idx,matchLen) + QString::fromLatin1(""); idx+=matchLen-1; break; } } result+=text[idx]; break; case 'w' : if((parseURLs)&& (text[idx+1].latin1()=='w')) { // don't do all the stuff for every 'w' regExp="^www\\.[^\\s<>()\"|]+\\.[^\\s<>()\"|]+"; if (regExp.match(text,idx,&matchLen)!=-1) { result+=QString::fromLatin1("") + text.mid(idx,matchLen) + QString::fromLatin1(""); idx+=matchLen-1; break; } } result+=text[idx]; break; case 'f' : if((parseURLs)&& (text[idx+1].latin1()=='t')) { // don't do all the stuff for every 'f' regExp="^ftp://[^\\s<>()\"|]+"; if (regExp.match(text,idx,&matchLen)!=-1) { result+=QString::fromLatin1("") + text.mid(idx,matchLen) + QString::fromLatin1(""); idx+=matchLen-1; break; } regExp="^ftp\\.[^\\s<>()\"|]+\\.[^\\s<>()\"|]+"; if (regExp.match(text,idx,&matchLen)!=-1) { result+=QString::fromLatin1("") + text.mid(idx,matchLen) + QString::fromLatin1(""); idx+=matchLen-1; break; } } result+=text[idx]; break; case '_' : case '/' : case '*' : if(beautification) { regExp=QString("^\\%1[^\\s%2]+\\%3").arg(text[idx]).arg(text[idx]).arg(text[idx]); if (regExp.match(text,idx,&matchLen)!=-1) { if (( matchLen > 3 ) && ((idx==0)||text[idx-1].isSpace()||(text[idx-1] == '(')) && ((idx+matchLen==len)||text[idx+matchLen].isSpace()||(text[idx+matchLen]==',')|| (text[idx+matchLen]=='.')||(text[idx+matchLen]==')'))) { switch (text[idx].latin1()) { case '_' : result+=QString("%1").arg(toHtmlString(text.mid(idx+1,matchLen-2),parseURLs,beautification)); break; case '/' : result+=QString("%1").arg(toHtmlString(text.mid(idx+1,matchLen-2),parseURLs,beautification)); break; case '*' : result+=QString("%1").arg(toHtmlString(text.mid(idx+1,matchLen-2),parseURLs,beautification)); break; } idx+=matchLen-1; break; } } } result+=text[idx]; break; default : result+=text[idx]; } } return result; } void KNArticleWidget::openURL(const QString &url) { if(url.isEmpty()) return; - if (knGlobals.cfgManager->readNewsGeneral()->browser()==KNConfig::ReadNewsGeneral::BTkonq) + if (knGlobals.cfgManager->readNewsViewer()->browser()==KNConfig::ReadNewsViewer::BTkonq) kapp->invokeBrowser(url); - else if (knGlobals.cfgManager->readNewsGeneral()->browser()==KNConfig::ReadNewsGeneral::BTnetscape){ + else if (knGlobals.cfgManager->readNewsViewer()->browser()==KNConfig::ReadNewsViewer::BTnetscape){ KProcess proc; proc << "netscape"; struct stat info; // QFileInfo is unable to handle netscape's broken symlink if (lstat((QDir::homeDirPath()+"/.netscape/lock").local8Bit(),&info)==0) proc << "-remote" << QString("openURL(%1)").arg(url); else proc << url; proc.start(KProcess::DontCare); } - else if (knGlobals.cfgManager->readNewsGeneral()->browser()==KNConfig::ReadNewsGeneral::BTmozilla){ + else if (knGlobals.cfgManager->readNewsViewer()->browser()==KNConfig::ReadNewsViewer::BTmozilla){ KProcess proc; proc << "run-mozilla.sh"; proc << "mozilla-bin"; proc << url; proc.start(KProcess::DontCare); } - else if (knGlobals.cfgManager->readNewsGeneral()->browser()==KNConfig::ReadNewsGeneral::BTopera){ + else if (knGlobals.cfgManager->readNewsViewer()->browser()==KNConfig::ReadNewsViewer::BTopera){ KProcess proc; proc << "opera"; proc << QString("-page=%1").arg(url); proc << url; proc.start(KProcess::DontCare); } else { KProcess proc; - QStringList command = QStringList::split(' ',knGlobals.cfgManager->readNewsGeneral()->browserCommand()); + QStringList command = QStringList::split(' ',knGlobals.cfgManager->readNewsViewer()->browserCommand()); bool urlAdded=false; for ( QStringList::Iterator it = command.begin(); it != command.end(); ++it ) { if ((*it).contains("%u")) { (*it).replace(QRegExp("%u"),url); urlAdded=true; } proc << (*it); } if(!urlAdded) // no %u in the browser command proc << url; proc.start(KProcess::DontCare); } } void KNArticleWidget::saveAttachment(int id) { KNMimeContent *a=a_tt->at(id); if(a) knGlobals.artManager->saveContentToFile(a); else KMessageBox::error(this, i18n("Internal error: Malformed identifier!")); } void KNArticleWidget::openAttachment(int id) { KNMimeContent *a=a_tt->at(id); if(a) knGlobals.artManager->openContent(a); else KMessageBox::error(this, i18n("Internal error: Malformed identifier!")); } bool KNArticleWidget::inlinePossible(KNMimeContent *c) { KNHeaders::ContentType *ct=c->contentType(); return ( ct->isText() || ct->isImage() ); } void KNArticleWidget::showBlankPage() { kdDebug(5003) << "KNArticleWidget::showBlankPage()" << endl; setText(QString::null); a_rticle=0; delete a_tt; a_tt=0; h_tmlDone=false; a_ctSave->setEnabled(false); a_ctPrint->setEnabled(false); a_ctCopy->setEnabled(false); //probaly not neede, but who knows ;-) a_ctSelAll->setEnabled(false); a_ctReply->setEnabled(false); a_ctRemail->setEnabled(false); a_ctForward->setEnabled(false); a_ctCancel->setEnabled(false); a_ctSupersede->setEnabled(false); a_ctVerify->setEnabled(false); a_ctToggleFullHdrs->setEnabled(false); a_ctToggleRot13->setEnabled(false); a_ctSetCharset->setEnabled(false); } void KNArticleWidget::showErrorMessage(const QString &s) { setFont(knGlobals.cfgManager->appearance()->articleFont()); // switch back from possible obscure charsets QString msg=""+i18n("An error occured!

"); msg+=toHtmlString(s)+"
"; setText(msg); a_rticle=0; delete a_tt; a_tt=0; h_tmlDone=false; a_ctSave->setEnabled(false); a_ctPrint->setEnabled(false); a_ctSelAll->setEnabled(true); a_ctReply->setEnabled(false); a_ctRemail->setEnabled(false); a_ctForward->setEnabled(false); a_ctCancel->setEnabled(false); a_ctSupersede->setEnabled(false); a_ctVerify->setEnabled(false); a_ctToggleFullHdrs->setEnabled(false); a_ctToggleRot13->setEnabled(false); a_ctSetCharset->setEnabled(false); } void KNArticleWidget::updateContents() { if(a_rticle && a_rticle->hasContent()) createHtmlPage(); else showBlankPage(); } void KNArticleWidget::setArticle(KNArticle *a) { a_rticle=a; h_tmlDone=false; r_ot13=false; a_ctToggleRot13->setChecked(false); t_imer->stop(); if(!a) showBlankPage(); else { //kdDebug(5003) << "KNArticleWidget::setArticle() : " << a->messageID()->as7BitString(false) << endl; if(a->hasContent()) //article is already loaded => just show it createHtmlPage(); else if(!a->isLocked()) { if(a->type()==KNMimeBase::ATremote) {//ok, this is a remote-article => fetch it from the server KNGroup *g=static_cast(a->collection()); emitJob( new KNJobData( KNJobData::JTfetchArticle, this, g->account(), a_rticle ) ); } else { //local article KNLocalArticle *la=static_cast(a_rticle); KNFolder *f=static_cast(a_rticle->collection()); if(!f || !f->loadArticle(la)) showErrorMessage(i18n("Cannot load the article from the mbox-file!")); else createHtmlPage(); } } } } void KNArticleWidget::processJob(KNJobData *j) { KNRemoteArticle *a=static_cast(j->data()); if(j->canceled()) { articleChanged(a); } else { if(j->success()) { a->updateListItem(); articleChanged(a); } else if(a_rticle==a) showErrorMessage(j->errorString()); } delete j; } void KNArticleWidget::createHtmlPage() { kdDebug(5003) << "KNArticleWidget::createHtmlPage()" << endl; if(!a_rticle) { showBlankPage(); return; } if(!a_rticle->hasContent()) { showErrorMessage(i18n("the article contains no data")); return; } if ((forceCS!=a_rticle->forceDefaultCS())|| (forceCS && (a_rticle->defaultCharset()!=overrideCS))) { a_rticle->setDefaultCharset(overrideCS); a_rticle->setForceDefaultCS(forceCS); } KNConfig::Appearance *app=knGlobals.cfgManager->appearance(); - KNConfig::ReadNewsGeneral *rng=knGlobals.cfgManager->readNewsGeneral(); + KNConfig::ReadNewsViewer *rnv=knGlobals.cfgManager->readNewsViewer(); //-----------------------------------
--------------------------------------- QString html, hLine; html=QString(""; KNMimeContent *text=a_rticle->textContent(); if(text) { if(!text->canDecode8BitText()) { html+=QString("") .arg(i18n("Unknown charset! Default charset is used instead.")); kdDebug(5003) << "KNArticleWidget::createHtmlPage() : unknown charset = " << text->contentType()->charset() << " not available!" << endl; setFont(app->articleFont()); } else { QFont f=app->articleFont(); text->setFontForContent(f); setFont(f); } } else setFont(app->articleFont()); kdDebug(5003) << "KNArticleWidget::createHtmlPage() : font-family = " << font().family() << endl; html+="
") .arg(app->headerDecoHexcode()); if(f_ullHdrs) { KNStringSplitter split; split.init(a_rticle->head(), "\n"); QString temp; int pos; bool splitOk=split.first(); while(splitOk) { html+="").arg(toHtmlString(temp)); else html+=QString("%1") .arg(toHtmlString(temp.left(pos+1))) .arg(toHtmlString(temp.right(temp.length()-pos-2))); splitOk=split.next(); } } else { KNHeaders::Base *hb; KNDisplayedHeader *dh; KNConfig::DisplayedHeaders::Iterator it=knGlobals.cfgManager->displayedHeaders()->iterator(); for(; it.current(); ++it) { dh=it.current(); hb=a_rticle->getHeaderByType(dh->header().latin1()); if(!hb) continue; //header not found if(dh->hasName()) { html += QString(""; } } html+=QString("
"; temp=QString::fromLatin1(split.string().data(), split.string().length()); if( (pos=temp.find(':'))==-1 ) html+=QString("%1
%2
%1%2:%3") .arg(dh->nameOpenTag()).arg(toHtmlString(dh->translatedName())) .arg(dh->nameCloseTag()); } else html+="
"; html+=dh->headerOpenTag(); if(hb->is("From")) html+=QString("%1") .arg(toHtmlString(hb->asUnicodeString())); else if(hb->is("Date")) { KNHeaders::Date *date=static_cast(hb); html+=toHtmlString(KGlobal::locale()->formatDateTime(date->qdt(), false, true)); } else html+=toHtmlString(hb->asUnicodeString()); html += dh->headerCloseTag()+"
") .arg(app->headerDecoHexcode()); //References KNHeaders::References *refs=a_rticle->references(false); if(a_rticle->type()==KNMimeBase::ATremote && refs) { int refCnt=refs->count(); html+=QString("%1").arg(i18n("References:")); for(int refNr=0; refNr%2").arg(refNr).arg(refNr+1); } else html+=i18n("no references"); html+="
%1
"; //-----------------------------------
-------------------------------------- //------------------------------------- --------------------------------------- KNHeaders::ContentType *ct=a_rticle->contentType(); //Attachments if(!text || ct->isMultipart()) { if(a_tt) a_tt->clear(); else { a_tt=new KNMimeContent::List; a_tt->setAutoDelete(false); } - a_rticle->attachments(a_tt, rng->showAlternativeContents()); + a_rticle->attachments(a_tt, rnv->showAlternativeContents()); } else { delete a_tt; a_tt=0; } //Partial message if(ct->isPartial()) { html+=i18n("
This article has the Mime-Type "message/partial", which KNode cannot handle yet.
Meanwhile you can save the article as a text-file and reassemble it by hand.
"); setText(html); h_tmlDone=true; //enable actions a_ctReply->setEnabled(a_rticle->type()==KNMimeBase::ATremote); a_ctRemail->setEnabled(a_rticle->type()==KNMimeBase::ATremote); a_ctSave->setEnabled(true); a_ctPrint->setEnabled(true); a_ctSelAll->setEnabled(true); a_ctToggleFullHdrs->setEnabled(true); a_ctSetCharset->setEnabled(true); return; } //body text if(text && text->hasContent()) { html+=""; if(text->contentType()->isHTMLText()) { QString htmlTxt; text->decodedText(htmlTxt); setText(htmlTxt); // is this correct? what happens to the headers? (CG) } else { QChar firstChar; int oldLevel=0, newLevel=0; unsigned int idx=0; bool isSig=false; QStringList lines; QString line; text->decodedText(lines); for(QStringList::Iterator it=lines.begin(); it!=lines.end(); ++it) { line=(*it); if(!line.isEmpty()) { if(!isSig && line=="-- ") { isSig=true; if(newLevel>0) { newLevel=0; html+=""; } - if(rng->showSignature()) { + if(rnv->showSignature()) { html+="
"; continue; } else break; } if(!isSig) { idx=0; oldLevel=newLevel; newLevel=0; firstChar=line[idx]; while(idx < line.length()) { firstChar=line[idx]; if(firstChar.isSpace()) idx++; else if(firstChar.latin1()=='>') { idx++; newLevel++; } else break; } if(newLevel!=oldLevel) { if(newLevel==0) html+=""; else { if(newLevel>=3) newLevel=3; if(oldLevel>0) html+=""; html+=QString("").arg(app->quotedTextHexcode(newLevel-1)); } } } html+=toHtmlString(line,true,true,true)+"
"; } else html+="
"; } if(newLevel>0) html+="
"; } html+="
"; } //attachment table if(a_tt) { int attCnt=0; QString path; if(!a_tt->isEmpty()) { html+=""; html+=QString("") .arg(i18n("name")).arg(i18n("mime-type")).arg(i18n("description")); for(KNMimeContent *var=a_tt->first(); var; var=a_tt->next()) { ct=var->contentType(); html+=QString("") .arg(attCnt) .arg(ct->name()) .arg(ct->mimeType()) .arg(toHtmlString(var->contentDescription()->asUnicodeString())); - if(rng->showAttachmentsInline() && inlinePossible(var)) { + if(rnv->showAttachmentsInline() && inlinePossible(var)) { html+=""; } attCnt++; } html+="
%1%2%3
%2%3%4
"; if(ct->isImage()) { //image path=knGlobals.artManager->saveContentToTemp(var); if(!path.isEmpty()) { html+=QString("").arg(attCnt).arg(path); } } else { //text QString tmp; var->decodedText(tmp); if(ct->isHTMLText()) html+=tmp; else html+="
"+toHtmlString(tmp,true,false,true)+"
"; } html+="
"; } } //------------------------------------- -------------------------------------- //display html html+=""; setText(html); h_tmlDone=true; //enable actions a_ctSave->setEnabled(true); a_ctPrint->setEnabled(true); a_ctSelAll->setEnabled(true); a_ctReply->setEnabled(a_rticle->type()==KNMimeBase::ATremote); a_ctRemail->setEnabled(a_rticle->type()==KNMimeBase::ATremote); a_ctForward->setEnabled(true); a_ctCancel->setEnabled( (knGlobals.folManager->currentFolder()!=knGlobals.folManager->outbox()) && (knGlobals.folManager->currentFolder()!=knGlobals.folManager->drafts())); a_ctSupersede->setEnabled( (knGlobals.folManager->currentFolder()!=knGlobals.folManager->outbox()) && (knGlobals.folManager->currentFolder()!=knGlobals.folManager->drafts())); a_ctVerify->setEnabled(true); a_ctToggleFullHdrs->setEnabled(true); a_ctToggleRot13->setEnabled(true); a_ctSetCharset->setEnabled(true); //start automark-timer - if(a_rticle->type()==KNMimeBase::ATremote && rng->autoMark()) - t_imer->start( (rng->autoMarkSeconds()*1000), true); + if(a_rticle->type()==KNMimeBase::ATremote && knGlobals.cfgManager->readNewsGeneral()->autoMark()) + t_imer->start( (knGlobals.cfgManager->readNewsGeneral()->autoMarkSeconds()*1000), true); } void KNArticleWidget::setSource(const QString &s) { if(!s.isEmpty()) anchorClicked(s); } void KNArticleWidget::anchorClicked(const QString &a, ButtonState button, const QPoint *p) { anchorType type=ATunknown; QString target; if(a.left(15)=="internal:author") { type=ATauthor; } else if(a.left(13)=="internal:ref=") { target=a.mid(13, a.length()-13); type=ATreference; } else if(a.left(13)=="internal:att=") { target=a.mid(13, a.length()-13); type=ATattachment; } else if(a.left(7).lower()=="http://" ||a.left(6).lower()=="ftp://") { target=a; type=ATurl; } if((button==LeftButton)||(button==MidButton)) { KNGroup *g; KNRemoteArticle *a; switch(type) { case ATauthor: kdDebug(5003) << "KNArticleWidget::anchorClicked() : mailto author" << endl; knGlobals.artFactory->createMail(a_rticle->from()); break; case ATreference: kdDebug(5003) << "KNArticleWidget::anchorClicked() : reference " << target << endl; g=static_cast(a_rticle->collection()); a=g->byMessageId(a_rticle->references()->at(target.toInt())); if(a) setArticle(a); else showErrorMessage(i18n("Article %1 not found in group %2") .arg(a_rticle->references()->at(target.toInt())) .arg(g->groupname())); break; case ATattachment: kdDebug(5003) << "KNArticleWidget::anchorClicked() : attachment " << target << endl; - if(knGlobals.cfgManager->readNewsGeneral()->openAttachmentsOnClick()) + if(knGlobals.cfgManager->readNewsViewer()->openAttachmentsOnClick()) openAttachment(target.toInt()); else saveAttachment(target.toInt()); break; case ATurl: kdDebug(5003) << "KNArticleWidget::anchorClicked() : url " << target << endl;; openURL(target); break; default: kdDebug(5003) << "KNArticleWidget::anchorClicked() : unknown" << endl; break; } } else { if(type==ATattachment) { kdDebug(5003) << "KNArticleWidget::anchorClicked() : popup for attachment " << target << endl; switch(a_ttPopup->exec(*p)) { case PUP_OPEN: openAttachment(target.toInt()); break; case PUP_SAVE: saveAttachment(target.toInt()); break; } } else if(type==ATurl) { kdDebug(5003) << "KNArticleWidget::anchorClicked() : popup for url " << target << endl; switch(u_rlPopup->exec(*p)) { case PUP_OPEN: openURL(target); break; case PUP_COPYURL: QApplication::clipboard()->setText(target); break; } } } } void KNArticleWidget::slotSave() { kdDebug(5003) << "KNArticleWidget::slotSave()" << endl; if(a_rticle) knGlobals.artManager->saveArticleToFile(a_rticle); } void KNArticleWidget::slotPrint() { kdDebug(5003) << "KNArticleWidget::slotPrint()" << endl; QPrinter *printer=new QPrinter(); if(printer->setup(this)) { QPaintDeviceMetrics metrics(printer); QPainter p; const int margin=20; int yPos=0; KNHeaders::Base *hb=0; QString text; QString hdr; p.begin(printer); p.setFont( QFont(font().family(), 12, QFont::Bold) ); QFontMetrics fm=p.fontMetrics(); KNDisplayedHeader *dh; KNConfig::DisplayedHeaders::Iterator it=knGlobals.cfgManager->displayedHeaders()->iterator(); dh=it.current(); while(dh) { hb=a_rticle->getHeaderByType(dh->header().latin1()); if(hb && !hb->isEmpty()) { if(dh->hasName()) text=QString("%1: %2").arg(dh->translatedName()).arg(hb->asUnicodeString()); else text=hb->asUnicodeString(); p.drawText( 10, yPos+margin, metrics.width(), fm.lineSpacing(), ExpandTabs | DontClip, text ); if( (dh=++it)!=0 ) yPos+=fm.lineSpacing(); } else ++it; } yPos+=fm.lineSpacing()+10; QPen pen(QColor(0,0,0), 2); p.setPen(pen); p.drawLine(10, yPos+margin, metrics.width(), yPos+margin); yPos+=2*fm.lineSpacing(); p.setFont( QFont(font().family(), 10, QFont::Normal) ); fm=p.fontMetrics(); QStringList lines; KNMimeContent *txt=a_rticle->textContent(); if(txt) { txt->decodedText(lines); for(QStringList::Iterator it=lines.begin(); it!=lines.end(); ++it) { if(yPos+margin > metrics.height()) { printer->newPage(); yPos=0; } text=(*it); p.drawText( 10, yPos+margin, metrics.width(), fm.lineSpacing(), ExpandTabs | DontClip, text ); yPos+=fm.lineSpacing(); } } p.end(); } delete printer; } void KNArticleWidget::slotSelectAll() { kdDebug(5003) << "KNArticleWidget::slotSelectAll()" << endl; selectAll(); a_ctCopy->setEnabled(true); } void KNArticleWidget::slotReply() { kdDebug(5003) << "KNArticleWidget::slotReply()" << endl; if(a_rticle && a_rticle->type()==KNMimeBase::ATremote) knGlobals.artFactory->createReply(static_cast(a_rticle), selectedText(), true, false); } void KNArticleWidget::slotRemail() { kdDebug(5003) << "KNArticleWidget::slotRemail()" << endl; if(a_rticle && a_rticle->type()==KNMimeBase::ATremote) knGlobals.artFactory->createReply(static_cast(a_rticle), selectedText(), false, true); } void KNArticleWidget::slotForward() { kdDebug(5003) << "KNArticleWidget::slotForward()" << endl; knGlobals.artFactory->createForward(a_rticle); } void KNArticleWidget::slotCancel() { kdDebug(5003) << "KNArticleWidget::slotCancel()" << endl; knGlobals.artFactory->createCancel(a_rticle); } void KNArticleWidget::slotSupersede() { kdDebug(5003) << "KNArticleWidget::slotSupersede()" << endl; knGlobals.artFactory->createSupersede(a_rticle); } void KNArticleWidget::slotToggleFullHdrs() { kdDebug(5003) << "KNArticleWidget::slotToggleFullHdrs()" << endl; f_ullHdrs=!f_ullHdrs; updateContents(); } void KNArticleWidget::slotToggleRot13() { r_ot13=!r_ot13; updateContents(); } void KNArticleWidget::slotSetCharset(const QString &s) { if(s.isEmpty()) return; if (s == i18n("Automatic")) { forceCS=false; overrideCS=QFont::ISO_8859_1; } else { forceCS=true; overrideCS=KGlobal::charsets()->charsetForEncoding(s); } if (a_rticle && a_rticle->hasContent()) { a_rticle->setDefaultCharset(overrideCS); // the article will choose the correct default, a_rticle->setForceDefaultCS(forceCS); // when we disable the overdrive createHtmlPage(); } } void KNArticleWidget::slotTimeout() { KNRemoteArticle::List l; l.append((static_cast(a_rticle))); knGlobals.artManager->setRead(&l, true); } void KNArticleWidget::slotVerify() { knGlobals.artManager->verifyPGPSignature(a_rticle); } //-------------------------------------------------------------------------------------- QList KNArticleWidget::i_nstances; void KNArticleWidget::configChanged() { for(KNArticleWidget *i=i_nstances.first(); i; i=i_nstances.next()) i->applyConfig(); } void KNArticleWidget::articleRemoved(KNArticle *a) { for(KNArticleWidget *i=i_nstances.first(); i; i=i_nstances.next()) if(a==i->article()) i->showBlankPage(); } void KNArticleWidget::articleChanged(KNArticle *a) { for(KNArticleWidget *i=i_nstances.first(); i; i=i_nstances.next()) if(a==i->article()) i->updateContents(); } void KNArticleWidget::collectionRemoved(KNArticleCollection *c) { for(KNArticleWidget *i=i_nstances.first(); i; i=i_nstances.next()) if(i->article() && i->article()->collection()==c) i->showBlankPage(); } //============================================================================================================= // some standard headers static const char *predef[] = { "Approved","Content-Transfer-Encoding","Content-Type","Control","Date","Distribution", "Expires","Followup-To","From","Lines","Message-ID","Mime-Version","NNTP-Posting-Host", "Newsgroups","Organization","Path","References","Reply-To","Sender","Subject","Supersedes", "To", "User-Agent","X-Mailer","X-Newsreader","X-No-Archive","XRef",0 }; // default display names KNode uses static const char *disp[] = { "Groups", 0 }; void dummyHeader() { i18n("collection of article headers","Approved"); i18n("collection of article headers","Content-Transfer-Encoding"); i18n("collection of article headers","Content-Type"); i18n("collection of article headers","Control"); i18n("collection of article headers","Date"); i18n("collection of article headers","Distribution"); i18n("collection of article headers","Expires"); i18n("collection of article headers","Followup-To"); i18n("collection of article headers","From"); i18n("collection of article headers","Lines"); i18n("collection of article headers","Message-ID"); i18n("collection of article headers","Mime-Version"); i18n("collection of article headers","NNTP-Posting-Host"); i18n("collection of article headers","Newsgroups"); i18n("collection of article headers","Organization"); i18n("collection of article headers","Path"); i18n("collection of article headers","References"); i18n("collection of article headers","Reply-To"); i18n("collection of article headers","Sender"); i18n("collection of article headers","Subject"); i18n("collection of article headers","Supersedes"); i18n("collection of article headers","To"); i18n("collection of article headers","User-Agent"); i18n("collection of article headers","X-Mailer"); i18n("collection of article headers","X-Newsreader"); i18n("collection of article headers","X-No-Archive"); i18n("collection of article headers","XRef"); i18n("collection of article headers","Groups"); } //============================================================================================================= KNDisplayedHeader::KNDisplayedHeader() : t_ranslateName(true) { f_lags.fill(false, 8); f_lags[1] = true; // header name bold by default } KNDisplayedHeader::~KNDisplayedHeader() { } // some common headers const char** KNDisplayedHeader::predefs() { return predef; } // *trys* to translate the name QString KNDisplayedHeader::translatedName() { if (t_ranslateName) { // major hack alert !!! if (!n_ame.isEmpty()) { if (i18n("collection of article headers",n_ame.local8Bit())!=n_ame.local8Bit().data()) // try to guess if this english or not return i18n("collection of article headers",n_ame.local8Bit()); else return n_ame; } else return QString::null; } else return n_ame; } // *trys* to retranslate the name to english void KNDisplayedHeader::setTranslatedName(const QString &s) { bool retranslated = false; for (const char **c=predef;(*c)!=0;c++) { // ok, first the standard header names if (s==i18n("collection of article headers",*c)) { n_ame = QString::fromLatin1(*c); retranslated = true; break; } } if (!retranslated) { for (const char **c=disp;(*c)!=0;c++) // now our standard display names if (s==i18n("collection of article headers",*c)) { n_ame = QString::fromLatin1(*c); retranslated = true; break; } } if (!retranslated) { // ok, we give up and store the maybe non-english string n_ame = s; t_ranslateName = false; // and don't try to translate it, so a german user *can* use the original english name } else t_ranslateName = true; } void KNDisplayedHeader::createTags() { const char *tokens[] = { "","","","", "","","","" }; for(int i=0; i<4; i++) t_ags[i]=QString::null; if(f_lags.at(0)) { // t_ags[0]=tokens[0]; t_ags[1]=tokens[1]; } if(f_lags.at(4)) { t_ags[2]=tokens[0]; t_ags[3]=tokens[1]; } if(f_lags.at(1)) { // t_ags[0]+=(tokens[2]); t_ags[1].prepend(tokens[3]); } if(f_lags.at(5)) { t_ags[2]+=tokens[2]; t_ags[3].prepend(tokens[3]); } if(f_lags.at(2)) { // t_ags[0]+=tokens[4]; t_ags[1].prepend(tokens[5]); } if(f_lags.at(6)) { t_ags[2]+=tokens[4]; t_ags[3].prepend(tokens[5]); } if(f_lags.at(3)) { // t_ags[0]+=tokens[6]; t_ags[1].prepend(tokens[7]); } if(f_lags.at(7)) { t_ags[2]+=tokens[6]; t_ags[3].prepend(tokens[7]); } } //-------------------------------- #include "knarticlewidget.moc" diff --git a/knode/knconfig.cpp b/knode/knconfig.cpp index 7a686a9ec7..fdf9accc24 100644 --- a/knode/knconfig.cpp +++ b/knode/knconfig.cpp @@ -1,1037 +1,1067 @@ /* knconfig.cpp KNode, the KDE newsreader Copyright (c) 1999-2000 the KNode authors. See file AUTHORS for details This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, US */ #include "knconfig.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "knglobals.h" #include "knnntpaccount.h" #include "knaccountmanager.h" #include "kngroupmanager.h" #include "knarticlewidget.h" #include "utilities.h" KNConfig::Identity::Identity(bool g) : g_lobal(g) { if(g_lobal) { KConfig *c=KGlobal::config(); c->setGroup("IDENTITY"); loadConfig(c); } } KNConfig::Identity::~Identity() {} void KNConfig::Identity::loadConfig(KConfigBase *c) { n_ame=c->readEntry("Name"); e_mail=c->readEntry("Email"); r_eplyTo=c->readEntry("Reply-To"); o_rga=c->readEntry("Org"); u_seSigFile=c->readBoolEntry("UseSigFile",false); s_igPath=c->readEntry("sigFile"); s_igText=c->readEntry("sigText"); } void KNConfig::Identity::saveConfig(KConfigBase *c) { c->writeEntry("Name", n_ame); c->writeEntry("Email", e_mail); c->writeEntry("Reply-To", r_eplyTo); c->writeEntry("Org", o_rga); c->writeEntry("UseSigFile", u_seSigFile); c->writeEntry("sigFile", s_igPath); c->writeEntry("sigText", s_igText); } void KNConfig::Identity::save() { kdDebug(5003) << "KNConfig::Identity::save()" << endl; if(g_lobal) { KConfig *c=KGlobal::config(); c->setGroup("IDENTITY"); saveConfig(c); } } bool KNConfig::Identity::isEmpty() { return ( n_ame.isEmpty() && e_mail.isEmpty() && r_eplyTo.isEmpty() && o_rga.isEmpty() && ( s_igPath.isEmpty() || s_igText.isEmpty() ) ); } bool KNConfig::Identity::emailIsValid() { if (e_mail.isEmpty()) return false; else return e_mail.contains(QRegExp("?*@?*.??*",true,true)); } QString KNConfig::Identity::getSignature() { s_igContents = QString::null; // don't cache file contents if (u_seSigFile) { if(!s_igPath.isEmpty()) { QFile f(s_igPath); if(f.open(IO_ReadOnly)) { QTextStream ts(&f); while(!ts.atEnd()) { s_igContents += ts.readLine(); if (!ts.atEnd()) s_igContents += "\n"; } f.close(); } else KMessageBox::error(knGlobals.topWidget, i18n("Cannot open the signature file!")); } } else s_igContents = s_igText; if (!s_igContents.isEmpty() && !s_igContents.contains("\n-- \n") && !(s_igContents.left(4) == "-- \n")) s_igContents.prepend("-- \n"); return s_igContents; } //============================================================================================================== KNConfig::Appearance::Appearance() { KConfig *c=KGlobal::config(); c->setGroup("VISUAL_APPEARANCE"); l_ongGroupList=c->readBoolEntry("longGroupList", true); //colors u_seColors=c->readBoolEntry("customColors", false); QColor defCol=kapp->palette().active().base(); c_olors[background]=c->readColorEntry("backgroundColor",&defCol); c_olorNames[background]=i18n("Background"); defCol=kapp->palette().active().background(); c_olors[header]=c->readColorEntry("headerColor",&defCol); c_olorNames[header]=i18n("Header Decoration"); defCol=kapp->palette().active().text(); c_olors[normalText]=c->readColorEntry("textColor",&defCol); c_olorNames[normalText]=i18n("Normal Text"); defCol=kapp->palette().active().text(); c_olors[quoted1]=c->readColorEntry("quote1Color",&defCol); c_olorNames[quoted1]=i18n("Quoted Text - First level"); defCol=kapp->palette().active().text(); c_olors[quoted2]=c->readColorEntry("quote2Color",&defCol); c_olorNames[quoted2]=i18n("Quoted Text - Second level"); defCol=kapp->palette().active().text(); c_olors[quoted3]=c->readColorEntry("quote3Color",&defCol); c_olorNames[quoted3]=i18n("Quoted Text - Third level"); defCol=KGlobalSettings::linkColor(); c_olors[url]=c->readColorEntry("URLColor",&defCol); c_olorNames[url]=i18n("Link"); defCol=kapp->palette().disabled().text(); c_olors[readArticle]=c->readColorEntry("readArticleColor",&defCol); c_olorNames[readArticle]=i18n("Read Article"); defCol=kapp->palette().active().text(); c_olors[unreadArticle]=c->readColorEntry("unreadArticleColor",&defCol); c_olorNames[unreadArticle]=i18n("Unread Article"); defCol=kapp->palette().active().highlight(); c_olors[activeItem]=c->readColorEntry("activeItemColor",&defCol); c_olorNames[activeItem]=i18n("Active Item Background"); defCol=kapp->palette().active().background(); c_olors[selectedItem]=c->readColorEntry("selectedItemColor",&defCol); c_olorNames[selectedItem]=i18n("Selected Item Background"); //fonts u_seFonts = c->readBoolEntry("customFonts", false); QFont defFont=KGlobalSettings::generalFont(); f_onts[article]=c->readFontEntry("articleFont",&defFont); f_ontNames[article]=i18n("Article Body"); f_onts[composer]=c->readFontEntry("composerFont",&defFont); f_ontNames[composer]=i18n("Composer"); f_onts[groupList]=c->readFontEntry("groupListFont",&defFont); f_ontNames[groupList]=i18n("Group List"); f_onts[articleList]=c->readFontEntry("articleListFont",&defFont); f_ontNames[articleList]=i18n("Article List"); updateHexcodes(); //icons i_cons[greyBall] = UserIcon("greyball"); i_cons[redBall] = UserIcon("redball"); i_cons[greyBallChkd] = UserIcon("greyballchk"); i_cons[redBallChkd] = UserIcon("redballchk"); i_cons[newFups] = UserIcon("newsubs"); i_cons[eyes] = UserIcon("eyes"); i_cons[mail] = SmallIcon("mail_generic"); i_cons[posting] = SmallIcon("filenew"); i_cons[canceledPosting] = SmallIcon("editdelete"); i_cons[nntp] = UserIcon("server"); i_cons[group] = UserIcon("group"); i_cons[folder] = SmallIcon("folder"); i_cons[sendErr] = UserIcon("snderr"); } KNConfig::Appearance::~Appearance() { } void KNConfig::Appearance::save() { kdDebug(5003) << "KNConfig::Appearance::save()" << endl; KConfig *c=KGlobal::config(); c->setGroup("VISUAL_APPEARANCE"); c->writeEntry("longGroupList", l_ongGroupList); c->writeEntry("customColors", u_seColors); c->writeEntry("backgroundColor", c_olors[background]); c->writeEntry("headerColor", c_olors[header]); c->writeEntry("textColor", c_olors[normalText]); c->writeEntry("quote1Color", c_olors[quoted1]); c->writeEntry("quote2Color", c_olors[quoted2]); c->writeEntry("quote3Color", c_olors[quoted3]); c->writeEntry("URLColor", c_olors[url]); c->writeEntry("readArticleColor", c_olors[readArticle]); c->writeEntry("unreadArticleColor", c_olors[unreadArticle]); c->writeEntry("activeItemColor", c_olors[activeItem]); c->writeEntry("selectedItemColor", c_olors[selectedItem]); c->writeEntry("customFonts", u_seFonts); c->writeEntry("articleFont", f_onts[article]); c->writeEntry("composerFont", f_onts[composer]); c->writeEntry("groupListFont", f_onts[groupList]); c->writeEntry("articleListFont", f_onts[articleList]); updateHexcodes(); } QColor KNConfig::Appearance::backgroundColor() { if(u_seColors) return c_olors[background]; else return kapp->palette().active().base(); } QColor KNConfig::Appearance::textColor() { if(u_seColors) return c_olors[normalText]; else return kapp->palette().active().text(); } QColor KNConfig::Appearance::quoteColor1() { if(u_seColors) return c_olors[quoted1]; else return kapp->palette().active().text(); } QColor KNConfig::Appearance::quoteColor2() { if(u_seColors) return c_olors[quoted2]; else return kapp->palette().active().text(); } QColor KNConfig::Appearance::quoteColor3() { if(u_seColors) return c_olors[quoted3]; else return kapp->palette().active().text(); } QColor KNConfig::Appearance::linkColor() { if(u_seColors) return c_olors[url]; else return KGlobalSettings::linkColor(); } QColor KNConfig::Appearance::headerDecoColor() { if(u_seColors) return c_olors[header]; else return kapp->palette().active().background(); } QColor KNConfig::Appearance::unreadArticleColor() { if(u_seColors) return c_olors[unreadArticle]; else return kapp->palette().active().text(); } QColor KNConfig::Appearance::readArticleColor() { if(u_seColors) return c_olors[readArticle]; else return kapp->palette().disabled().text(); } QColor KNConfig::Appearance::activeItemColor() { if(u_seColors) return c_olors[activeItem]; else return kapp->palette().active().highlight(); } QColor KNConfig::Appearance::selectedItemColor() { if(u_seColors) return c_olors[selectedItem]; else return kapp->palette().active().background(); } QFont KNConfig::Appearance::articleFont() { if(u_seFonts) return f_onts[article]; else return KGlobalSettings::generalFont(); } QFont KNConfig::Appearance::composerFont() { if(u_seFonts) return f_onts[composer]; else return KGlobalSettings::generalFont(); } QFont KNConfig::Appearance::groupListFont() { if(u_seFonts) return f_onts[groupList]; else return KGlobalSettings::generalFont(); } QFont KNConfig::Appearance::articleListFont() { if(u_seFonts) return f_onts[articleList]; else return KGlobalSettings::generalFont(); } void KNConfig::Appearance::updateHexcodes() { sprintf(h_excodes[quoted1Hex], "#%2x%2x%2x", quoteColor1().red(), quoteColor1().green(), quoteColor1().blue()); sprintf(h_excodes[quoted2Hex], "#%2x%2x%2x", quoteColor2().red(), quoteColor2().green(), quoteColor2().blue()); sprintf(h_excodes[quoted3Hex], "#%2x%2x%2x", quoteColor3().red(), quoteColor3().green(), quoteColor3().blue()); sprintf(h_excodes[headerHex], "#%2x%2x%2x", headerDecoColor().red(), headerDecoColor().green(), headerDecoColor().blue()); } QColor KNConfig::Appearance::defaultColor(int i) { switch(i) { case background: return kapp->palette().active().base(); break; case header: return kapp->palette().active().background(); break; case normalText: case quoted1: case quoted2: case quoted3: case unreadArticle: return kapp->palette().active().text(); break; case url: return KGlobalSettings::linkColor(); break; case readArticle: return kapp->palette().disabled().text(); break; case activeItem: return kapp->palette().active().highlight(); break; case selectedItem: return kapp->palette().active().background(); break; } return kapp->palette().disabled().text(); } QFont KNConfig::Appearance::defaultFont(int) { return KGlobalSettings::generalFont(); } //============================================================================================================== KNConfig::ReadNewsGeneral::ReadNewsGeneral() { KConfig *conf=KGlobal::config(); conf->setGroup("READNEWS"); a_utoCheck=conf->readBoolEntry("autoCheck", true); + m_axFetch=conf->readNumEntry("maxFetch", 1000); + if (m_axFetch<0) m_axFetch = 0; a_utoMark=conf->readBoolEntry("autoMark", true); + m_arkSecs=conf->readNumEntry("markSecs", 5); + if (m_arkSecs<0) m_arkSecs = 0; t_otalExpand=conf->readBoolEntry("totalExpand", true); + s_howLines=conf->readBoolEntry("showLines", false); + s_howScore=conf->readBoolEntry("showScore", true); +} + + +KNConfig::ReadNewsGeneral::~ReadNewsGeneral() +{ +} + + +void KNConfig::ReadNewsGeneral::save() +{ + kdDebug(5003) << "KNConfig::ReadNewsGeneral::save()" << endl; + + KConfig *conf=KGlobal::config(); + conf->setGroup("READNEWS"); + + conf->writeEntry("autoCheck", a_utoCheck); + conf->writeEntry("maxFetch", m_axFetch); + conf->writeEntry("autoMark", a_utoMark); + conf->writeEntry("markSecs", m_arkSecs); + conf->writeEntry("totalExpand", t_otalExpand); + conf->writeEntry("showLines", s_howLines); + conf->writeEntry("showScore", s_howScore); +} + + +//============================================================================================================== + + +KNConfig::ReadNewsViewer::ReadNewsViewer() +{ + KConfig *conf=KGlobal::config(); + conf->setGroup("READNEWS"); + s_howSig=conf->readBoolEntry("showSig", true); i_nterpretFormatTags=conf->readBoolEntry("interpretFormatTags", true); i_nlineAtt=conf->readBoolEntry("inlineAtt", true); o_penAtt=conf->readBoolEntry("openAtt", false) ; s_howAlts=conf->readBoolEntry("showAlts", false); - m_axFetch=conf->readNumEntry("maxFetch", 1000); - if (m_axFetch<0) m_axFetch = 0; - m_arkSecs=conf->readNumEntry("markSecs", 5); - if (m_arkSecs<0) m_arkSecs = 0; QString s = conf->readEntry("Browser","Konqueror"); if (s=="Netscape") b_rowser = BTnetscape; else if (s=="Mozilla") b_rowser = BTmozilla; else if (s=="Opera") b_rowser = BTopera; else if (s=="Other") b_rowser = BTother; else b_rowser = BTkonq; b_rowserCommand=conf->readEntry("BrowserCommand","netscape %u"); } -KNConfig::ReadNewsGeneral::~ReadNewsGeneral() +KNConfig::ReadNewsViewer::~ReadNewsViewer() { } -void KNConfig::ReadNewsGeneral::save() +void KNConfig::ReadNewsViewer::save() { - kdDebug(5003) << "KNConfig::ReadNewsGeneral::save()" << endl; + kdDebug(5003) << "KNConfig::ReadNewsViewer::save()" << endl; KConfig *conf=KGlobal::config(); conf->setGroup("READNEWS"); - conf->writeEntry("autoCheck", a_utoCheck); - conf->writeEntry("autoMark", a_utoMark); - conf->writeEntry("totalExpand", t_otalExpand); conf->writeEntry("showSig", s_howSig); conf->writeEntry("interpretFormatTags", i_nterpretFormatTags); conf->writeEntry("inlineAtt", i_nlineAtt); conf->writeEntry("openAtt", o_penAtt); conf->writeEntry("showAlts", s_howAlts); - conf->writeEntry("maxFetch", m_axFetch); - conf->writeEntry("markSecs", m_arkSecs); switch (b_rowser) { case BTkonq: conf->writeEntry("Browser","Konqueror"); break; case BTnetscape: conf->writeEntry("Browser","Netscape"); break; case BTmozilla: conf->writeEntry("Browser","Mozilla"); break; case BTopera: conf->writeEntry("Browser","Opera"); break; case BTother: conf->writeEntry("Browser","Other"); break; } conf->writeEntry("BrowserCommand", b_rowserCommand); } //============================================================================================================== KNConfig::DisplayedHeaders::DisplayedHeaders() { h_drList.setAutoDelete(true); QString fname(KGlobal::dirs()->findResource("appdata","headers.rc")); if (fname != QString::null) { KSimpleConfig headerConf(fname,true); QStringList headers = headerConf.groupList(); headers.remove(""); headers.sort(); KNDisplayedHeader *h; QValueList flags; QStringList::Iterator it; for( it = headers.begin(); it != headers.end(); ++it ) { h=createNewHeader(); headerConf.setGroup((*it)); h->setName(headerConf.readEntry("Name")); h->setTranslateName(headerConf.readBoolEntry("Translate_Name",true)); h->setHeader(headerConf.readEntry("Header")); flags=headerConf.readIntListEntry("Flags"); if(h->name().isNull() || h->header().isNull() || (flags.count()!=8)) { kdDebug(5003) << "KNConfig::DisplayedHeaders::DisplayedHeaders() : ignoring invalid/incomplete Header" << endl; remove(h); } else { for (int i=0; i<8; i++) h->setFlag(i, (flags[i]>0)); h->createTags(); } } } } KNConfig::DisplayedHeaders::~DisplayedHeaders() { } void KNConfig::DisplayedHeaders::save() { kdDebug(5003) << "KNConfig::DisplayedHeaders::save()" << endl; QString dir(KGlobal::dirs()->saveLocation("appdata")); if (dir==QString::null) { displayInternalFileError(); return; } KSimpleConfig headerConf(dir+"headers.rc"); QStringList oldHeaders = headerConf.groupList(); QStringList::Iterator oldIt=oldHeaders.begin(); for( ;oldIt != oldHeaders.end(); ++oldIt ) // remove all old groups headerConf.deleteGroup((*oldIt)); // find a better way to do it? QValueList flags; int idx=0; QString group; for(Iterator it(h_drList); it.current(); ++it) { group.setNum(idx++); while (group.length()<3) group.prepend("0"); headerConf.setGroup(group); headerConf.writeEntry("Name",(*it)->name()); headerConf.writeEntry("Translate_Name",(*it)->translateName()); headerConf.writeEntry("Header",(*it)->header()); flags.clear(); for (int i=0; i<8; i++) { if ((*it)->flag(i)) flags << 1; else flags << 0; } headerConf.writeEntry("Flags",flags); } } KNDisplayedHeader* KNConfig::DisplayedHeaders::createNewHeader() { KNDisplayedHeader *h=new KNDisplayedHeader(); h_drList.append(h); return h; } void KNConfig::DisplayedHeaders::remove(KNDisplayedHeader *h) { if (!h_drList.remove(h)) kdDebug(5003) << "KNConfig::DisplayedHeaders::remove() : cannot find pointer in list!" << endl; } void KNConfig::DisplayedHeaders::up(KNDisplayedHeader *h) { int idx=h_drList.findRef(h); if(idx!=-1) { h_drList.take(idx); h_drList.insert(idx-1, h); } else kdDebug(5003) << "KNConfig::DisplayedHeaders::up() : item not found in list" << endl; } void KNConfig::DisplayedHeaders::down(KNDisplayedHeader *h) { int idx=h_drList.findRef(h); if(idx!=-1) { h_drList.take(idx); h_drList.insert(idx+1, h); } else kdDebug(5003) << "KNConfig::DisplayedHeaders::down() : item not found in list" << endl; } //============================================================================================================== KNConfig::XHeader::XHeader(const QString &s) { if(s.left(2)=="X-") { int pos=s.find(": "); if(pos!=-1) { n_ame=s.mid(2, pos-2).latin1(); pos+=2; v_alue=s.mid(pos, s.length()-pos); } } } //============================================================================================================== KNConfig::PostNewsTechnical::PostNewsTechnical() : findComposerCSCache(113) { findComposerCSCache.setAutoDelete(true); KConfig *conf=KGlobal::config(); conf->setGroup("POSTNEWS"); c_omposerCharsets=conf->readListEntry("ComposerCharsets"); if (c_omposerCharsets.isEmpty()) c_omposerCharsets=QStringList::split(',',"us-ascii,utf-8,iso-8859-1,iso-8859-2," "iso-8859-3,iso-8859-4,iso-8859-5,iso-8859-6,iso-8859-7,iso-8859-8," "iso-8859-9,iso-8859-10,iso-8859-13,iso-8859-14,iso-8859-15,koi8-r,koi8-u," "iso-2022-jp,iso-2022-jp-2,iso-2022-kr,euc-jp,euc-kr,Big5,gb2312"); c_harset=conf->readEntry("Charset").latin1(); if (c_harset.isEmpty()) { c_harset=findComposerCharset(KGlobal::charsets()->charsetForLocale()); if (c_harset.isEmpty()) c_harset="iso-8859-1"; // shit } h_ostname=conf->readEntry("MIdhost").latin1(); a_llow8BitBody=conf->readBoolEntry("8BitEncoding",true); u_seOwnCharset=conf->readBoolEntry("UseOwnCharset",true); a_llow8BitHeaders=conf->readBoolEntry("allow8bitChars", false); g_enerateMID=conf->readBoolEntry("generateMId", false); d_ontIncludeUA=conf->readBoolEntry("dontIncludeUA", false); QString dir(KGlobal::dirs()->saveLocation("appdata")); if (dir!=QString::null) { QFile f(dir+"xheaders"); if(f.open(IO_ReadOnly)) { QTextStream ts(&f); while(!ts.eof()) x_headers.append( XHeader(ts.readLine()) ); f.close(); } } } KNConfig::PostNewsTechnical::~PostNewsTechnical() { } void KNConfig::PostNewsTechnical::save() { kdDebug(5003) << "KNConfig::PostNewsTechnical::save()" << endl; KConfig *conf=KGlobal::config(); conf->setGroup("POSTNEWS"); conf->writeEntry("ComposerCharsets", c_omposerCharsets); conf->writeEntry("Charset", QString::fromLatin1(c_harset)); conf->writeEntry("8BitEncoding", a_llow8BitBody); conf->writeEntry("UseOwnCharset", u_seOwnCharset); conf->writeEntry("allow8bitChars", a_llow8BitHeaders); conf->writeEntry("generateMId", g_enerateMID); conf->writeEntry("MIdhost", QString::fromLatin1(h_ostname)); conf->writeEntry("dontIncludeUA", d_ontIncludeUA); QString dir(KGlobal::dirs()->saveLocation("appdata")); if (dir==QString::null) displayInternalFileError(); else { QFile f(dir+"xheaders"); if(f.open(IO_WriteOnly)) { QTextStream ts(&f); XHeaders::Iterator it; for(it=x_headers.begin(); it!=x_headers.end(); ++it) ts << (*it).header() << "\n"; f.close(); } else displayInternalFileError(); } } int KNConfig::PostNewsTechnical::indexForCharset(const QCString &str) { int i=0; bool found=false; for ( QStringList::Iterator it = c_omposerCharsets.begin(); it != c_omposerCharsets.end(); ++it ) { if ((*it).lower() == str.lower().data()) { found = true; break; } i++; } if (!found) { i=0; for ( QStringList::Iterator it = c_omposerCharsets.begin(); it != c_omposerCharsets.end(); ++it ) { if ((*it).lower() == c_harset.lower().data()) { found = true; break; } i++; } if (!found) i=0; } return i; } QCString KNConfig::PostNewsTechnical::findComposerCharset(QCString cs) { QCString *ret=findComposerCSCache.find(cs); if (ret) return *ret; QFont::CharSet qfcs = KGlobal::charsets()->charsetForEncoding(cs); QCString s; QStringList::Iterator it; for( it = c_omposerCharsets.begin(); it != c_omposerCharsets.end(); ++it ) { // match by name if ((*it).lower()==cs.lower().data()) { s = (*it).latin1(); break; } // match by charset, avoid to return "us-ascii" for iso-8859-1 if (((*it).lower()!="us-ascii")&& (KGlobal::charsets()->charsetForEncoding(*it)==qfcs)) { s = (*it).latin1(); break; } } if (!s.isEmpty()) findComposerCSCache.insert(cs, new QCString(s)); return s; } QCString KNConfig::PostNewsTechnical::findComposerCharset(QFont::CharSet cs) { if (cs==QFont::ISO_8859_1) // avoid to return "us-ascii" return "iso-8859-1"; QCString *ret=findComposerCSCache.find(QString::number((int)(cs)).latin1()); if (ret) return *ret; QCString s; QStringList::Iterator it; for( it = c_omposerCharsets.begin(); it != c_omposerCharsets.end(); ++it ) { if ((KGlobal::charsets()->charsetForEncoding(*it)==cs)) { s = (*it).latin1(); break; } } if (!s.isEmpty()) findComposerCSCache.insert(QString::number((int)(cs)).latin1(), new QCString(s)); return s; } //============================================================================================================== KNConfig::PostNewsComposer::PostNewsComposer() { KConfig *conf=KGlobal::config(); conf->setGroup("POSTNEWS"); w_ordWrap=conf->readBoolEntry("wordWrap",true); m_axLen=conf->readNumEntry("maxLength", 76); a_ppSig=conf->readBoolEntry("appSig",true); r_ewrap=conf->readBoolEntry("rewrap",true); i_ncSig=conf->readBoolEntry("incSig",false); u_seExtEditor=conf->readBoolEntry("useExternalEditor",false); i_ntro=conf->readEntry("Intro","%NAME wrote:"); e_xternalEditor=conf->readEntry("externalEditor","kwrite %f"); } KNConfig::PostNewsComposer::~PostNewsComposer() { } void KNConfig::PostNewsComposer::save() { kdDebug(5003) << "KNConfig::PostNewsComposer::save()" << endl; KConfig *conf=KGlobal::config(); conf->setGroup("POSTNEWS"); conf->writeEntry("wordWrap", w_ordWrap); conf->writeEntry("maxLength", m_axLen); conf->writeEntry("appSig", a_ppSig); conf->writeEntry("rewrap",r_ewrap); conf->writeEntry("incSig", i_ncSig); conf->writeEntry("useExternalEditor", u_seExtEditor); conf->writeEntry("Intro", i_ntro); conf->writeEntry("externalEditor", e_xternalEditor); } //============================================================================================================== KNConfig::Privacy::Privacy() : v_ersions ( QStringList() << "GnuPG 1.x" << "PGP 2.6.x" << "PGP 5" << "PGP 6" ), e_ncodings ( QStringList() << "Text" ) { KConfig *conf = KGlobal::config(); conf->setGroup("PRIVACY"); v_ersion = conf->readNumEntry("pgpVersion",GPG1); k_eeppasswd = conf->readBoolEntry("keepPassword",false); k_eyserv = conf->readEntry("keyserver"); e_ncoding = conf->readNumEntry("encoding",0); p_rogpath = conf->readEntry("progPath"); if (p_rogpath.isEmpty()) p_rogpath = defaultProg(v_ersion); } KNConfig::Privacy::~Privacy() { } // overrides KNConfig::Base::save() void KNConfig::Privacy::save() { kdDebug(5003) << "KNConfig::Privacy::save()" << endl; KConfig *conf = KGlobal::config(); conf->setGroup("PRIVACY"); conf->writeEntry("pgpVersion",v_ersion); conf->writeEntry("keepPassword",k_eeppasswd); conf->writeEntry("keyserver",k_eyserv); conf->writeEntry("encoding",e_ncoding); conf->writeEntry("progPath",p_rogpath); } QString KNConfig::Privacy::defaultProg(int version) { QString pgp; if (version == GPG1) pgp = "/gpg"; else pgp = "/pgp"; QStringList pSearchPaths=QStringList::split(':',QString::fromLocal8Bit(getenv("PATH"))); for (QStringList::Iterator it = pSearchPaths.begin(); it != pSearchPaths.end(); ++it ) { if (QFileInfo((*it)+pgp).isExecutable()) return (*it)+pgp; } return QString::null; } //============================================================================================================== KNConfig::Cleanup::Cleanup() { KConfig *conf=KGlobal::config(); conf->setGroup("EXPIRE"); d_oExpire=conf->readBoolEntry("doExpire", true); p_reserveThr=conf->readBoolEntry("saveThreads",true); d_oCompact=conf->readBoolEntry("doCompact", true); e_xpireInterval=conf->readNumEntry("expInterval", 5); r_eadMaxAge=conf->readNumEntry("readDays",10); u_nreadMaxAge=conf->readNumEntry("unreadDays",15); c_ompactInterval=conf->readNumEntry("comInterval", 5); } KNConfig::Cleanup::~Cleanup() { } void KNConfig::Cleanup::save() { kdDebug(5003) << "KNConfig::Cleanup::save()" << endl; KConfig *conf=KGlobal::config(); conf->setGroup("EXPIRE"); conf->writeEntry("doExpire", d_oExpire); conf->writeEntry("saveThreads", p_reserveThr); conf->writeEntry("doCompact", d_oCompact); conf->writeEntry("expInterval", e_xpireInterval); conf->writeEntry("readDays", r_eadMaxAge); conf->writeEntry("unreadDays", u_nreadMaxAge); conf->writeEntry("comInterval", c_ompactInterval); } bool KNConfig::Cleanup::expireToday() { if(!d_oExpire) return false; KConfig *c=KGlobal::config(); c->setGroup("EXPIRE"); QDate today=QDate::currentDate(); QDate lastExpDate=c->readDateTimeEntry("lastExpire").date(); if(lastExpDate==today) { c->writeEntry("lastExpire", QDateTime::currentDateTime()); // important! otherwise lastExpDate will be at its default value (current date) forever return false; } return (lastExpDate.daysTo(today) >= e_xpireInterval); } void KNConfig::Cleanup::setLastExpireDate() { KConfig *c=KGlobal::config(); c->setGroup("EXPIRE"); c->writeEntry("lastExpire", QDateTime::currentDateTime()); } bool KNConfig::Cleanup::compactToday() { if(!d_oCompact) return false; KConfig *c=KGlobal::config(); c->setGroup("EXPIRE"); QDate today=QDate::currentDate(); QDate lastComDate=c->readDateTimeEntry("lastCompact").date(); if(lastComDate==today) { c->writeEntry("lastCompact", QDateTime::currentDateTime()); // important! otherwise lastComDate will be at its default value (current date) forever return false; } return (lastComDate.daysTo(today) >= c_ompactInterval); } void KNConfig::Cleanup::setLastCompactDate() { KConfig *c=KGlobal::config(); c->setGroup("EXPIRE"); c->writeEntry("lastCompact", QDateTime::currentDateTime()); } diff --git a/knode/knconfig.h b/knode/knconfig.h index 5a088a3274..02c247398f 100644 --- a/knode/knconfig.h +++ b/knode/knconfig.h @@ -1,981 +1,1018 @@ /* knconfig.h KNode, the KDE newsreader Copyright (c) 1999-2000 the KNode authors. See file AUTHORS for details This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, US */ #ifndef KNCONFIG_H #define KNCONFIG_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "knlistbox.h" class KNNntpAccount; class KNAccountManager; class KNArticleFilter; class KNFilterManager; class KNDisplayedHeader; class KNServerInfo; namespace KNConfig { class Base { public: Base() {} virtual ~Base() {} virtual void save() {} }; class BaseWidget : public QWidget { Q_OBJECT public: BaseWidget(QWidget *p=0, const char *n=0) : QWidget(p, n), d_irty(false) {} ~BaseWidget() {} void show() { d_irty=true; QWidget::show(); } bool dirty() { return d_irty; } void setDirty(bool b) { d_irty=b; } virtual void apply() {} protected: bool d_irty; }; class Identity : public Base { friend class IdentityWidget; public: Identity(bool g=true); ~Identity(); void loadConfig(KConfigBase *c); void saveConfig(KConfigBase *c); void save(); bool isEmpty(); bool isGlobal() { return g_lobal; } //personal information bool hasName() { return (!n_ame.isEmpty()); } QString name() { return n_ame; } void setName(const QString &s) { n_ame=s; } bool emailIsValid(); bool hasEmail() { return (!e_mail.isEmpty()); } QString email() { return e_mail; } void setEmail(const QCString &s) { e_mail=s; } bool hasReplyTo() { return (!r_eplyTo.isEmpty()); } QString replyTo() { return r_eplyTo; } void setReplyTo(const QString &s) { r_eplyTo=s; } bool hasOrga() { return (!o_rga.isEmpty()); } QString orga() { return o_rga; } void setOrga(const QString &s) { o_rga=s; } //signature bool hasSignature() { return ( (u_seSigFile && !s_igPath.isEmpty()) || !s_igText.isEmpty() ); } bool useSigFile() { return u_seSigFile; } QString sigPath() { return s_igPath; } QString sigText() { return s_igText; } QString getSignature(); protected: QString n_ame, e_mail, o_rga, r_eplyTo, s_igText, s_igContents, s_igPath; bool u_seSigFile, g_lobal; }; class IdentityWidget : public BaseWidget { Q_OBJECT public: IdentityWidget(Identity *d, QWidget *p=0, const char *n=0); ~IdentityWidget(); void apply(); protected: QLabel *f_ileName; QLineEdit *n_ame, *o_rga, *e_mail, *r_eplyTo, *s_ig; QRadioButton *s_igFile, *s_igEdit; QPushButton *c_hooseBtn, *e_ditBtn; QMultiLineEdit *s_igEditor; Identity *d_ata; protected slots: void slotSignatureType(int type); void slotSignatureChoose(); void slotSignatureEdit(); }; class NntpAccountListWidget : public BaseWidget { Q_OBJECT public: NntpAccountListWidget(QWidget *p=0, const char *n=0); ~NntpAccountListWidget(); protected: class LBoxItem : public KNListBoxItem { public: LBoxItem(KNNntpAccount *a, const QString &t, QPixmap *p=0) : KNListBoxItem(t, p) , account(a) {} ~LBoxItem() {} KNNntpAccount *account; }; QListBox *l_box; QPushButton *a_ddBtn, *d_elBtn, *e_ditBtn, *s_ubBtn; QPixmap p_ixmap; QLabel *s_erverInfo, *p_ortInfo; KNAccountManager *a_ccManager; public slots: void slotAddItem(KNNntpAccount *a); void slotRemoveItem(KNNntpAccount *a); void slotUpdateItem(KNNntpAccount *a); protected slots: void slotSelectionChanged(); void slotItemSelected(int id); void slotAddBtnClicked(); void slotDelBtnClicked(); void slotEditBtnClicked(); void slotSubBtnClicked(); }; class NntpAccountConfDialog : public KDialogBase { Q_OBJECT public: NntpAccountConfDialog(KNNntpAccount* acc, QWidget *p=0, const char *n=0); ~NntpAccountConfDialog(); protected: QLineEdit *n_ame, *s_erver, *u_ser, *p_ass, *p_ort; QLabel *u_serLabel, *p_assLabel; KIntSpinBox *h_old, *t_imeout; QCheckBox *f_etchDes, *a_uth; KNNntpAccount *a_ccount; protected slots: void slotOk(); void slotAuthChecked(bool b); }; class SmtpAccountWidget : public BaseWidget { public: SmtpAccountWidget(QWidget *p=0, const char *n=0); ~SmtpAccountWidget(); void apply(); protected: KNServerInfo *s_erverInfo; QLineEdit *s_erver, *p_ort; KIntSpinBox *h_old, *t_imeout; }; class Appearance : public Base { #define COL_CNT 11 #define FNT_CNT 4 #define HEX_CNT 4 #define ICON_CNT 14 friend class AppearanceWidget; public: enum ColorIndex { background=0, header=1, normalText=2, quoted1=3, quoted2=4, quoted3=5, url=6, unreadArticle=7, readArticle=8,activeItem=9, selectedItem=10 }; enum HexIndex { quoted1Hex=0, quoted2Hex=1, quoted3Hex=2, headerHex=3 }; enum FontIndex { article=0, composer=1, groupList=2, articleList=3 }; enum IconIndex { greyBall=0, redBall=1, greyBallChkd=2, redBallChkd=3, newFups=4, eyes=5, mail=6, posting=7, canceledPosting=8, nntp=9, group=10, folder=11, sendErr=12, null=13 }; Appearance(); ~Appearance(); void save(); bool longGroupList() { return l_ongGroupList; } QColor backgroundColor(); QColor textColor(); QColor quoteColor1(); QColor quoteColor2(); QColor quoteColor3(); QColor linkColor(); QColor headerDecoColor(); QColor unreadArticleColor(); QColor readArticleColor(); QColor activeItemColor(); QColor selectedItemColor(); const char* headerDecoHexcode() { return h_excodes[headerHex]; } const char* quotedTextHexcode(int i) { return h_excodes[i]; } void updateHexcodes(); QFont articleFont(); QFont composerFont(); QFont groupListFont(); QFont articleListFont(); const QPixmap& icon(IconIndex i) { return i_cons[i]; } protected: const QColor& color(int i) { return c_olors[i]; } const QString& colorName(int i) { return c_olorNames[i]; } int colorCount() { return COL_CNT; } QColor defaultColor(int i); const QFont& font(int i) { return f_onts[i]; } const QString& fontName(int i) { return f_ontNames[i]; } int fontCount() { return FNT_CNT; } QFont defaultFont(int); bool l_ongGroupList, u_seColors, u_seFonts; QColor c_olors[COL_CNT]; QString c_olorNames[COL_CNT]; QFont f_onts[FNT_CNT]; QString f_ontNames[FNT_CNT]; char h_excodes[HEX_CNT][8]; QPixmap i_cons[ICON_CNT]; }; class AppearanceWidget : public BaseWidget { Q_OBJECT public: AppearanceWidget(Appearance *d, QWidget *p=0, const char *n=0); ~AppearanceWidget(); void apply(); //=================================================================================== // code taken from KMail, Copyright (C) 2000 Espen Sand, espen@kde.org class ColorListItem : public QListBoxText { public: ColorListItem( const QString &text, const QColor &color=Qt::black ); ~ColorListItem(); const QColor& color() { return mColor; } void setColor( const QColor &color ) { mColor = color; } protected: virtual void paint( QPainter * ); virtual int height( const QListBox * ) const; virtual int width( const QListBox * ) const; private: QColor mColor; }; //=================================================================================== class FontListItem : public QListBoxText { public: FontListItem( const QString &name, const QFont & ); ~FontListItem(); const QFont& font() { return f_ont; } void setFont( const QFont &); protected: virtual void paint( QPainter * ); virtual int width( const QListBox * ) const; private: QFont f_ont; QString fontInfo; }; //=================================================================================== QListBox *c_List, *f_List; QCheckBox *l_ongCB, *c_olorCB, *f_ontCB; QPushButton *c_olDefBtn, *c_olChngBtn, *f_ntDefBtn, *f_ntChngBtn; Appearance *d_ata; protected slots: //colors void slotColCheckBoxToggled(bool b); void slotColItemSelected(QListBoxItem *); // show color dialog for the entry void slotColDefaultBtnClicked(); void slotColChangeBtnClicked(); void slotColSelectionChanged(); //fonts void slotFontCheckBoxToggled(bool b); void slotFontItemSelected(QListBoxItem *); // show font dialog for the entry void slotFontDefaultBtnClicked(); void slotFontChangeBtnClicked(); void slotFontSelectionChanged(); }; class ReadNewsGeneral : public Base { friend class ReadNewsGeneralWidget; public: - enum browserType { BTkonq=0, BTnetscape=1, BTmozilla=2, BTopera=3, BTother=4 }; - ReadNewsGeneral(); ~ReadNewsGeneral(); void save(); bool autoCheckGroups() { return a_utoCheck; } int maxToFetch() { return m_axFetch; } bool autoMark() { return a_utoMark; } int autoMarkSeconds() { return m_arkSecs; } bool totalExpandThreads() { return t_otalExpand; } + bool showLines() { return s_howLines; } + bool showScore() { return s_howScore; } + + protected: + bool a_utoCheck, + a_utoMark, + t_otalExpand, + s_howLines, + s_howScore; + + int m_axFetch, + m_arkSecs; + +}; + + +class ReadNewsGeneralWidget : public BaseWidget { + + public: + ReadNewsGeneralWidget(ReadNewsGeneral *d, QWidget *p=0, const char *n=0); + ~ReadNewsGeneralWidget(); + + void apply(); + + protected: + QCheckBox *a_utoCB, + *m_arkCB, + *e_xpThrCB, + *l_inesCB, + *s_coreCB; + KIntSpinBox *m_arkSecs, + *m_axFetch; + + ReadNewsGeneral *d_ata; + +}; + + +class ReadNewsViewer : public Base { + + friend class ReadNewsViewerWidget; + + public: + enum browserType { BTkonq=0, BTnetscape=1, BTmozilla=2, BTopera=3, BTother=4 }; + + ReadNewsViewer(); + ~ReadNewsViewer(); + + void save(); + bool showSignature() { return s_howSig; } bool interpretFormatTags() { return i_nterpretFormatTags; } bool showAttachmentsInline() { return i_nlineAtt; } bool openAttachmentsOnClick() { return o_penAtt; } bool showAlternativeContents() { return s_howAlts; } browserType browser() { return b_rowser; } QString browserCommand() { return b_rowserCommand; } protected: - bool a_utoCheck, - a_utoMark, - t_otalExpand, - s_howSig, + bool s_howSig, i_nterpretFormatTags, i_nlineAtt, o_penAtt, s_howAlts; - int m_axFetch, - m_arkSecs; - browserType b_rowser; QString b_rowserCommand; }; -class ReadNewsGeneralWidget : public BaseWidget { +class ReadNewsViewerWidget : public BaseWidget { Q_OBJECT public: - ReadNewsGeneralWidget(ReadNewsGeneral *d, QWidget *p=0, const char *n=0); - ~ReadNewsGeneralWidget(); + ReadNewsViewerWidget(ReadNewsViewer *d, QWidget *p=0, const char *n=0); + ~ReadNewsViewerWidget(); void apply(); protected: - QCheckBox *a_utoCB, - *m_arkCB, - *s_igCB, + QCheckBox *s_igCB, *i_nlineCB, *o_penAttCB, - *e_xpThrCB, *a_ltAttCB, *f_ormatCB; - KIntSpinBox *m_arkSecs, - *m_axFetch; QComboBox *b_rowser; QLineEdit *b_rowserCommand; QPushButton *c_hooseBrowser; - ReadNewsGeneral *d_ata; + ReadNewsViewer *d_ata; protected slots: - void slotMarkReadToggled(bool); void slotBrowserTypeChanged(int); void slotChooseBrowser(); }; + class DisplayedHeaders : public Base { friend class DisplayedHeadersWidget; public: typedef QListIterator Iterator; DisplayedHeaders(); ~DisplayedHeaders(); void save(); KNDisplayedHeader* createNewHeader(); void remove(KNDisplayedHeader *h); void up(KNDisplayedHeader *h); void down(KNDisplayedHeader *h); Iterator iterator() { return Iterator(h_drList); } protected: QList h_drList; }; class DisplayedHeadersWidget : public BaseWidget { Q_OBJECT public: DisplayedHeadersWidget(DisplayedHeaders *d, QWidget *p=0, const char *n=0); ~DisplayedHeadersWidget(); protected: class HdrItem : public QListBoxText { public: HdrItem( const QString &t, KNDisplayedHeader *h ) : QListBoxText(t), hdr(h) {} ~HdrItem() {} KNDisplayedHeader *hdr; }; HdrItem* generateItem(KNDisplayedHeader *); QListBox *l_box; QPushButton *a_ddBtn, *d_elBtn, *e_ditBtn, *u_pBtn, *d_ownBtn; bool s_ave; DisplayedHeaders *d_ata; protected slots: void slotItemSelected(int); void slotSelectionChanged(); void slotAddBtnClicked(); void slotDelBtnClicked(); void slotEditBtnClicked(); void slotUpBtnClicked(); void slotDownBtnClicked(); }; class DisplayedHeaderConfDialog : public KDialogBase { Q_OBJECT public: DisplayedHeaderConfDialog(KNDisplayedHeader *h, QWidget *p=0, char *n=0); ~DisplayedHeaderConfDialog(); protected: KNDisplayedHeader *h_dr; QComboBox *h_drC; QLineEdit *n_ameE; QCheckBox *n_ameCB[4], *v_alueCB[4]; protected slots: void slotOk(); void slotActivated(int); void slotNameChanged(const QString&); }; class FilterListWidget : public BaseWidget { Q_OBJECT public: FilterListWidget(QWidget *p=0, const char *n=0); ~FilterListWidget(); void apply(); void addItem(KNArticleFilter *f); void removeItem(KNArticleFilter *f); void updateItem(KNArticleFilter *f); void addMenuItem(KNArticleFilter *f); void removeMenuItem(KNArticleFilter *f); QValueList menuOrder(); protected: class LBoxItem : public KNListBoxItem { public: LBoxItem(KNArticleFilter *f, const QString &t, QPixmap *p=0) : KNListBoxItem(t, p) , filter(f) {} ~LBoxItem() {} KNArticleFilter *filter; }; int findItem(QListBox *l, KNArticleFilter *f); QListBox *f_lb, *m_lb; QPushButton *a_ddBtn, *d_elBtn, *e_ditBtn, *c_opyBtn, *u_pBtn, *d_ownBtn, *s_epAddBtn, *s_epRemBtn; QPixmap a_ctive, d_isabled; KNFilterManager *f_ilManager; protected slots: void slotAddBtnClicked(); void slotDelBtnClicked(); void slotEditBtnClicked(); void slotCopyBtnClicked(); void slotUpBtnClicked(); void slotDownBtnClicked(); void slotSepAddBtnClicked(); void slotSepRemBtnClicked(); void slotItemSelectedFilter(int); void slotSelectionChangedFilter(); void slotSelectionChangedMenu(); }; class XHeader { public: XHeader() {} XHeader(const QString &s); XHeader(const XHeader &s) { n_ame=s.n_ame; v_alue=s.v_alue; } ~XHeader() {} XHeader& operator=(const XHeader &s) { n_ame=s.n_ame; v_alue=s.v_alue; return (*this); } QCString name() { return n_ame; } QString value() { return v_alue; } QString header() { return (QString::fromLatin1(("X-"+n_ame+": "))+v_alue); } protected: QCString n_ame; QString v_alue; }; typedef QValueList XHeaders; class PostNewsTechnical : public Base { friend class PostNewsTechnicalWidget; public: PostNewsTechnical(); ~PostNewsTechnical(); void save(); QCString charset() { return c_harset; } QStringList composerCharsets() { return c_omposerCharsets; } int indexForCharset(const QCString &str); QCString findComposerCharset(QCString cs); QCString findComposerCharset(QFont::CharSet cs); bool allow8BitBody() { return a_llow8BitBody; } bool useOwnCharset() { return u_seOwnCharset; } bool allow8BitHeaders() { return a_llow8BitHeaders; } bool generateMessageID() { return g_enerateMID; } QCString hostname() { return h_ostname; } XHeaders& xHeaders() { return x_headers; } bool noUserAgent() { return d_ontIncludeUA; } protected: QCString c_harset, h_ostname; QStringList c_omposerCharsets; bool a_llow8BitBody, u_seOwnCharset, a_llow8BitHeaders, g_enerateMID, d_ontIncludeUA; XHeaders x_headers; QAsciiDict findComposerCSCache; }; class PostNewsTechnicalWidget : public BaseWidget { Q_OBJECT public: PostNewsTechnicalWidget(PostNewsTechnical *d, QWidget *p=0, const char *n=0); ~PostNewsTechnicalWidget(); void apply(); protected: QComboBox *c_harset, *e_ncoding; QCheckBox *u_seOwnCSCB, *a_llow8bitCB, *g_enMIdCB, *i_ncUaCB; QListBox *l_box; QPushButton *a_ddBtn, *d_elBtn, *e_ditBtn; QLineEdit *h_ost; QLabel *h_ostL; PostNewsTechnical *d_ata; protected slots: void slotHeadEncToggled(bool b); void slotGenMIdCBToggled(bool b); void slotSelectionChanged(); void slotItemSelected(int id); void slotAddBtnClicked(); void slotDelBtnClicked(); void slotEditBtnClicked(); }; class XHeaderConfDialog : public KDialogBase { public: XHeaderConfDialog(const QString &h=QString::null, QWidget *p=0, const char *n=0); ~XHeaderConfDialog(); QString result(); protected: QLineEdit *n_ame, *v_alue; }; class PostNewsComposer : public Base { friend class PostNewsComposerWidget; public: PostNewsComposer(); ~PostNewsComposer(); void save(); bool wordWrap() { return w_ordWrap; } int maxLineLength() { return m_axLen; } bool appendOwnSignature() { return a_ppSig; } QString intro() { return i_ntro; } bool rewrap() { return r_ewrap; } bool includeSignature() { return i_ncSig; } QString externalEditor() { return e_xternalEditor; } bool useExternalEditor() { return u_seExtEditor; } protected: int m_axLen; bool w_ordWrap, a_ppSig, r_ewrap, i_ncSig, u_seExtEditor; QString i_ntro, e_xternalEditor; }; class PostNewsComposerWidget : public BaseWidget { Q_OBJECT public: PostNewsComposerWidget(PostNewsComposer *d, QWidget *p=0, const char *n=0); ~PostNewsComposerWidget(); void apply(); protected: KIntSpinBox *m_axLen; QCheckBox *w_ordWrapCB, *o_wnSigCB, *a_uthSigCB, *r_ewrapCB, *e_xternCB; QLineEdit *i_ntro, *e_ditor; PostNewsComposer *d_ata; protected slots: void slotChooseEditor(); }; class PostNewsSpellingWidget : public BaseWidget { public: PostNewsSpellingWidget(QWidget *p=0, const char *n=0); ~PostNewsSpellingWidget(); void apply(); protected: KSpellConfig *c_onf; }; class Privacy: public Base { friend class PrivacyWidget; public: Privacy(); ~Privacy(); void save(); enum { GPG1 = 0, PGP2, PGP5, PGP6 }; QString defaultProg(int version); private: // k_eyserv is the used Keyserver QString k_eyserv; // p_rogpath is the path to the used PGP program, ie /usr/bin/gpg QString p_rogpath; // k_eyring is the used Keyring QString k_eyring; // v_ersions contains a list of currently supported PGP/GPG versions const QStringList v_ersions; // e_ncodings contains a list of currently supported message encodings // (that means something like where to store the signature in an article) const QStringList e_ncodings; // v_version is the used version, its in fact the offset in the v_ersions list int v_ersion; // e_ncoding is the used encoding, its in fact the offset in the e_ncodings list int e_ncoding; // shall knode store the passphrase in memory? (thats an security hole, but really handy) bool k_eeppasswd; }; class PrivacyWidget : public BaseWidget { Q_OBJECT public: PrivacyWidget(Privacy *p, QWidget *p=0, const char *n=0); ~PrivacyWidget(); void apply(); // overrides BaseWidget::apply() protected: Privacy* d_ata; QComboBox *pgp_version, *enc_style; QCheckBox *keeppasswd; QLineEdit *keyring, *keyserv, *pgp_path; protected slots: void slotDefaultProg(int); void slotChoosePgp(); }; class Cleanup : public Base { friend class CleanupWidget; public: Cleanup(); ~Cleanup(); void save(); //expire int maxAgeForRead() { return r_eadMaxAge; } int maxAgeForUnread() { return u_nreadMaxAge; } bool preserveThreads() { return p_reserveThr; } bool expireToday(); void setLastExpireDate(); //compact bool compactToday(); void setLastCompactDate(); protected: bool d_oExpire, p_reserveThr, d_oCompact; int e_xpireInterval, r_eadMaxAge, u_nreadMaxAge, c_ompactInterval; }; class CleanupWidget : public BaseWidget { Q_OBJECT public: CleanupWidget(Cleanup *d, QWidget *p=0, const char *n=0); ~CleanupWidget(); void apply(); protected: QCheckBox *f_olderCB, *g_roupCB, *t_hrCB; KIntSpinBox *f_olderDays, *g_roupDays, *r_eadDays, *u_nreadDays; QLabel *f_olderDaysL, *g_roupDaysL, *r_eadDaysL, *u_nreadDaysL; Cleanup *d_ata; protected slots: void slotGroupCBtoggled(bool b); void slotFolderCBtoggled(bool b); }; }; //KNConfig #endif //KNCONFIG_H diff --git a/knode/knconfigmanager.cpp b/knode/knconfigmanager.cpp index 1be9ab8631..4c5189f86a 100644 --- a/knode/knconfigmanager.cpp +++ b/knode/knconfigmanager.cpp @@ -1,196 +1,205 @@ /* knconfigmanager.cpp KNode, the KDE newsreader Copyright (c) 1999-2000 the KNode authors. See file AUTHORS for details This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, US */ #include "knconfigmanager.h" #include #include #include #include #include #include "utilities.h" #include "knglobals.h" #include "knarticlewidget.h" #include "knarticlefactory.h" #include "knodeview.h" + KNConfigManager::KNConfigManager(QObject *p, const char *n) : QObject(p, n), d_ialog(0) { i_dentity = new KNConfig::Identity(); a_ppearance = new KNConfig::Appearance(); r_eadNewsGeneral = new KNConfig::ReadNewsGeneral(); + r_eadNewsViewer = new KNConfig::ReadNewsViewer(); d_isplayedHeaders = new KNConfig::DisplayedHeaders(); p_ostNewsTechnical = new KNConfig::PostNewsTechnical(); p_ostNewsCompose = new KNConfig::PostNewsComposer(); c_leanup = new KNConfig::Cleanup(); p_rivacy = new KNConfig::Privacy(); } KNConfigManager::~KNConfigManager() { delete i_dentity; delete a_ppearance; delete r_eadNewsGeneral; + delete r_eadNewsViewer; delete d_isplayedHeaders; delete p_ostNewsTechnical; delete p_ostNewsCompose; delete c_leanup; delete p_rivacy; } void KNConfigManager::configure() { if(!d_ialog) { d_ialog=new KNConfigDialog(this, knGlobals.topWidget, "Preferences_Dlg"); connect(d_ialog, SIGNAL(finished()), this, SLOT(slotDialogDone())); d_ialog->show(); } else KWin::setActiveWindow(d_ialog->winId()); } void KNConfigManager::slotDialogDone() { d_ialog->delayedDestruct(); d_ialog=0; } //=================================================================================================== KNConfigDialog::KNConfigDialog(KNConfigManager *m, QWidget *p, const char *n) : KDialogBase(TreeList, i18n("Preferences"), Ok|Apply|Cancel|Help, Ok, p, n, false, true) { setShowIconsInTreeList(true); // setRootIsDecorated(false); QStringList list; // Set up the folder bitmaps list << QString(" ")+i18n("Accounts"); setFolderIcon(list, UserIcon("server")); list.clear(); list << QString(" ")+i18n("Reading News"); setFolderIcon(list, BarIcon("mail_get")); list.clear(); list << QString(" ")+i18n("Posting News"); setFolderIcon(list, BarIcon("mail_forward")); // Identity QFrame *frame = addHBoxPage(i18n("Identity"),i18n("Personal Information"), BarIcon("identity", KIcon::SizeMedium )); w_idgets.append(new KNConfig::IdentityWidget(m->identity(), frame)); // Accounts / News list.clear(); list << QString(" ")+i18n("Accounts") << i18n(" News"); frame = addHBoxPage(list, i18n("Newsgroups Servers"), UserIcon("group")); w_idgets.append(new KNConfig::NntpAccountListWidget(frame)); // Accounts / Mail list.clear(); list << QString(" ")+i18n("Accounts") << i18n(" Mail"); frame = addHBoxPage(list, i18n("Mail Server (SMTP)"), BarIcon("mail_generic")); w_idgets.append(new KNConfig::SmtpAccountWidget(frame)); // Appearance frame = addHBoxPage(QString(" ")+i18n("Appearance"), i18n("Customize visual appearance"), BarIcon("appearance")); w_idgets.append(new KNConfig::AppearanceWidget(m->appearance(), frame)); // Read News / General list.clear(); list << QString(" ")+i18n("Reading News") << QString(" ")+i18n("General"); frame = addHBoxPage(list, i18n("General Options"), BarIcon("misc")); w_idgets.append(new KNConfig::ReadNewsGeneralWidget(m->readNewsGeneral(), frame)); - // Read News // Headers + // Read News / Filters + list.clear(); + list << QString(" ")+i18n("Reading News") << i18n(" Filters"); + frame = addHBoxPage(list,i18n("Article Filters"),BarIcon("filter")); + w_idgets.append(new KNConfig::FilterListWidget(frame)); + + // Read News / Headers list.clear(); list << QString(" ")+i18n("Reading News") << QString(" ")+i18n("Headers"); frame = addHBoxPage(list, i18n("Customize displayed article headers"), BarIcon("text_block")); w_idgets.append(new KNConfig::DisplayedHeadersWidget(m->displayedHeaders(), frame)); - // Read News / Filters + // Read News / Viewer list.clear(); - list << QString(" ")+i18n("Reading News") << i18n(" Filters"); - frame = addHBoxPage(list,i18n("Article Filters"),BarIcon("filter")); - w_idgets.append(new KNConfig::FilterListWidget(frame)); + list << QString(" ")+i18n("Reading News") << QString(" ")+i18n("Viewer"); + frame = addHBoxPage(list, i18n("Customize article viewer behaviour"), BarIcon("contents")); + w_idgets.append(new KNConfig::ReadNewsViewerWidget(m->readNewsViewer(), frame)); // Post News / Technical list.clear(); list << QString(" ")+i18n("Posting News") << QString(" ")+i18n("Technical"); frame = addHBoxPage(list, i18n("Technical Settings"), BarIcon("configure")); w_idgets.append(new KNConfig::PostNewsTechnicalWidget(m->postNewsTechnical(), frame)); // Post News / Composer list.clear(); list << QString(" ")+i18n("Posting News") << QString(" ")+i18n("Composer"); frame = addHBoxPage(list, i18n("Customize composer behaviour"), BarIcon("signature")); w_idgets.append(new KNConfig::PostNewsComposerWidget(m->postNewsComposer(), frame)); // Post News / Spelling list.clear(); list << QString(" ")+i18n("Posting News") << QString(" ")+i18n("Spelling"); frame = addHBoxPage(list, i18n("Spell checker behavior"), BarIcon("spellcheck")); w_idgets.append(new KNConfig::PostNewsSpellingWidget(frame)); // Privacy frame = addHBoxPage(QString(" ")+i18n("Signing/Verifying"), i18n("Protect your privacy by signing and verifying postings"), BarIcon("password")); w_idgets.append(new KNConfig::PrivacyWidget(m->privacy(),frame)); // Cleanup frame = addHBoxPage(QString(" ")+i18n("Cleanup"),i18n("Preserving disk space"), BarIcon("wizard")); w_idgets.append(new KNConfig::CleanupWidget(m->cleanup(), frame)); restoreWindowSize("settingsDlg", this, QSize(508,424)); setHelp("anc-setting-your-identity"); } KNConfigDialog::~KNConfigDialog() { saveWindowSize("settingsDlg", this->size()); } void KNConfigDialog::slotApply() { for(KNConfig::BaseWidget *w=w_idgets.first(); w; w=w_idgets.next()) w->apply(); KNArticleWidget::configChanged(); knGlobals.view->configChanged(); knGlobals.artFactory->configChanged(); } void KNConfigDialog::slotOk() { slotApply(); KDialogBase::slotOk(); } //----------------------------- #include "knconfigmanager.moc" diff --git a/knode/knconfigmanager.h b/knode/knconfigmanager.h index 80cbca8e9e..f7cb336e58 100644 --- a/knode/knconfigmanager.h +++ b/knode/knconfigmanager.h @@ -1,89 +1,80 @@ /* knconfigmanager.h KNode, the KDE newsreader Copyright (c) 1999-2000 the KNode authors. See file AUTHORS for details This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, US */ #ifndef KNCONFIGMANAGER_H #define KNCONFIGMANAGER_H #include "knconfig.h" class KNConfigDialog; class KNConfigManager : QObject { Q_OBJECT public: KNConfigManager(QObject *p=0, const char *n=0); ~KNConfigManager(); - KNConfig::Identity* identity() { return i_dentity; } KNConfig::Appearance* appearance() { return a_ppearance; } KNConfig::ReadNewsGeneral* readNewsGeneral() { return r_eadNewsGeneral; } + KNConfig::ReadNewsViewer* readNewsViewer() { return r_eadNewsViewer; } KNConfig::DisplayedHeaders* displayedHeaders() { return d_isplayedHeaders; } KNConfig::PostNewsTechnical* postNewsTechnical() { return p_ostNewsTechnical; } KNConfig::PostNewsComposer* postNewsComposer() { return p_ostNewsCompose; } KNConfig::Cleanup* cleanup() { return c_leanup; } - KNConfig::Privacy* privacy() { return p_rivacy; } + KNConfig::Privacy* privacy() { return p_rivacy; } void configure(); - protected: KNConfig::Identity *i_dentity; KNConfig::Appearance *a_ppearance; KNConfig::ReadNewsGeneral *r_eadNewsGeneral; + KNConfig::ReadNewsViewer *r_eadNewsViewer; KNConfig::DisplayedHeaders *d_isplayedHeaders; KNConfig::PostNewsTechnical *p_ostNewsTechnical; KNConfig::PostNewsComposer *p_ostNewsCompose; KNConfig::Cleanup *c_leanup; KNConfig::Privacy *p_rivacy; KNConfigDialog *d_ialog; - protected slots: void slotDialogDone(); }; class KNConfigDialog : public KDialogBase { Q_OBJECT public: KNConfigDialog(KNConfigManager *m, QWidget *p=0, const char *n=0); ~KNConfigDialog(); protected: QList w_idgets; protected slots: void slotApply(); void slotOk(); - - }; - - #endif //KNCONFIGMANAGER_H - - - - diff --git a/knode/knconfigwidgets.cpp b/knode/knconfigwidgets.cpp index 9bea5ce5ba..ddbf045d6e 100644 --- a/knode/knconfigwidgets.cpp +++ b/knode/knconfigwidgets.cpp @@ -1,2100 +1,2148 @@ /* knconfigwidgets.cpp KNode, the KDE newsreader Copyright (c) 1999-2000 the KNode authors. See file AUTHORS for details This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, US */ #include "knconfig.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "knaccountmanager.h" #include "kngroupmanager.h" #include "knglobals.h" #include "knnntpaccount.h" #include "utilities.h" #include "knarticlewidget.h" #include "knfiltermanager.h" #include "knarticlefilter.h" #include "knmime.h" KNConfig::IdentityWidget::IdentityWidget(Identity *d, QWidget *p, const char *n) : BaseWidget(p, n), d_ata(d) { QGridLayout *topL=new QGridLayout(this, 9, 3, 5,5); n_ame=new QLineEdit(this); QLabel *l=new QLabel(n_ame, i18n("&Name:"), this); topL->addWidget(l, 0,0); topL->addMultiCellWidget(n_ame, 0,0, 1,2); n_ame->setText(d_ata->n_ame); o_rga=new QLineEdit(this); l=new QLabel(o_rga, i18n("Organi&zation:"), this); topL->addWidget(l, 1,0); topL->addMultiCellWidget(o_rga, 1,1, 1,2); o_rga->setText(d_ata->o_rga); e_mail=new QLineEdit(this); l=new QLabel(e_mail, i18n("Email A&ddress:"), this); topL->addWidget(l, 2,0); topL->addMultiCellWidget(e_mail, 2,2, 1,2); e_mail->setText(d_ata->e_mail); r_eplyTo=new QLineEdit(this); l=new QLabel(r_eplyTo, i18n("&Reply-To Address:"), this); topL->addWidget(l, 3,0); topL->addMultiCellWidget(r_eplyTo, 3,3, 1,2); r_eplyTo->setText(d_ata->r_eplyTo); QButtonGroup *buttonGroup = new QButtonGroup(this); connect( buttonGroup, SIGNAL(clicked(int)), this, SLOT(slotSignatureType(int)) ); buttonGroup->hide(); s_igFile = new QRadioButton( i18n("&Use a signature from file"), this ); buttonGroup->insert(s_igFile); topL->addMultiCellWidget(s_igFile, 4, 4, 0, 2); s_ig = new QLineEdit(this); f_ileName = new QLabel(s_ig, i18n("Signature &File:"), this); topL->addWidget(f_ileName, 5, 0 ); topL->addWidget(s_ig, 5, 1 ); s_ig->setText(d_ata->s_igPath); c_hooseBtn = new QPushButton( i18n("Choo&se..."), this); connect(c_hooseBtn, SIGNAL(clicked()), this, SLOT(slotSignatureChoose())); topL->addWidget(c_hooseBtn, 5, 2 ); e_ditBtn = new QPushButton( i18n("&Edit File"), this); connect(e_ditBtn, SIGNAL(clicked()), this, SLOT(slotSignatureEdit())); topL->addWidget(e_ditBtn, 6, 2); s_igEdit = new QRadioButton( i18n("Specify signature &below"), this); buttonGroup->insert(s_igEdit); topL->addMultiCellWidget(s_igEdit, 7, 7, 0, 2); s_igEditor = new QMultiLineEdit(this); topL->addMultiCellWidget(s_igEditor, 8, 8, 0, 2); s_igEditor->setText(d_ata->s_igText); topL->setColStretch(1,1); topL->setRowStretch(5,1); topL->setResizeMode(QLayout::Minimum); slotSignatureType(d_ata->useSigFile()? 0:1); } KNConfig::IdentityWidget::~IdentityWidget() { } void KNConfig::IdentityWidget::apply() { if(!d_irty) return; d_ata->n_ame=n_ame->text(); d_ata->o_rga=o_rga->text(); d_ata->e_mail=e_mail->text(); d_ata->r_eplyTo=r_eplyTo->text(); d_ata->u_seSigFile=s_igFile->isChecked(); d_ata->s_igPath=s_ig->text(); d_ata->s_igText=s_igEditor->text(); if(d_ata->isGlobal()) d_ata->save(); } void KNConfig::IdentityWidget::slotSignatureType(int type) { bool sigFromFile = (type==0); s_igFile->setChecked(sigFromFile); f_ileName->setEnabled(sigFromFile); s_ig->setEnabled(sigFromFile); c_hooseBtn->setEnabled(sigFromFile); e_ditBtn->setEnabled(sigFromFile); s_igEdit->setChecked(!sigFromFile); s_igEditor->setEnabled(!sigFromFile); if (sigFromFile) f_ileName->setFocus(); else s_igEditor->setFocus(); } void KNConfig::IdentityWidget::slotSignatureChoose() { QString tmp=KFileDialog::getOpenFileName(s_ig->text(),QString::null,this,i18n("Choose Signature")); if(!tmp.isEmpty()) s_ig->setText(tmp); } void KNConfig::IdentityWidget::slotSignatureEdit() { QString fileName = s_ig->text().stripWhiteSpace(); if (fileName.isEmpty()) { KMessageBox::sorry(this, i18n("You must specify a filename!")); return; } QFileInfo fileInfo( fileName ); if (fileInfo.isDir()) { KMessageBox::sorry(this, i18n("You have specified a directory!")); return; } KService::Ptr offer = KServiceTypeProfile::preferredService("text/plain", true); KURL::List lst(fileName); if (offer) KRun::run(*offer, lst); else { KFileOpenWithHandler *openhandler = new KFileOpenWithHandler(); openhandler->displayOpenWithDialog(lst); } } //========================================================================================== KNConfig::NntpAccountListWidget::NntpAccountListWidget(QWidget *p, const char *n) : BaseWidget(p, n), p_ixmap(UserIcon("server")), a_ccManager(knGlobals.accManager) { QGridLayout *topL=new QGridLayout(this, 6,2, 5,5); // account listbox l_box=new QListBox(this); connect(l_box, SIGNAL(selected(int)), this, SLOT(slotItemSelected(int))); connect(l_box, SIGNAL(selectionChanged()), this, SLOT(slotSelectionChanged())); topL->addMultiCellWidget(l_box, 0,4, 0,0); // info box QGroupBox *gb = new QGroupBox(2,Qt::Vertical,QString::null,this); topL->addWidget(gb,5,0); s_erverInfo = new QLabel(gb); p_ortInfo = new QLabel(gb); // buttons a_ddBtn=new QPushButton(i18n("&New"), this); connect(a_ddBtn, SIGNAL(clicked()), this, SLOT(slotAddBtnClicked())); topL->addWidget(a_ddBtn, 0,1); d_elBtn=new QPushButton(i18n("&Delete"), this); connect(d_elBtn, SIGNAL(clicked()), this, SLOT(slotDelBtnClicked())); topL->addWidget(d_elBtn, 1,1); e_ditBtn=new QPushButton(i18n("modify something","&Edit"), this); connect(e_ditBtn, SIGNAL(clicked()), this, SLOT(slotEditBtnClicked())); topL->addWidget(e_ditBtn, 2,1); s_ubBtn=new QPushButton(i18n("&Subscribe"), this); connect(s_ubBtn, SIGNAL(clicked()), this, SLOT(slotSubBtnClicked())); topL->addWidget(s_ubBtn, 3,1); topL->setRowStretch(4,1); // stretch the server listbox for(KNNntpAccount *a=a_ccManager->first(); a; a=a_ccManager->next()) slotAddItem(a); // the settings dialog is non-modal, so we have to react to changes // made outside of the dialog connect(a_ccManager, SIGNAL(accountAdded(KNNntpAccount*)), this, SLOT(slotAddItem(KNNntpAccount*))); connect(a_ccManager, SIGNAL(accountRemoved(KNNntpAccount*)), this, SLOT(slotRemoveItem(KNNntpAccount*))); connect(a_ccManager, SIGNAL(accountModified(KNNntpAccount*)), this, SLOT(slotUpdateItem(KNNntpAccount*))); slotSelectionChanged(); // disable Delete & Edit initially } KNConfig::NntpAccountListWidget::~NntpAccountListWidget() { } void KNConfig::NntpAccountListWidget::slotAddItem(KNNntpAccount *a) { LBoxItem *it; it=new LBoxItem(a, a->name(), &p_ixmap); l_box->insertItem(it); } void KNConfig::NntpAccountListWidget::slotRemoveItem(KNNntpAccount *a) { LBoxItem *it; for(uint i=0; icount(); i++) { it=static_cast(l_box->item(i)); if(it && it->account==a) { l_box->removeItem(i); break; } } slotSelectionChanged(); } void KNConfig::NntpAccountListWidget::slotUpdateItem(KNNntpAccount *a) { LBoxItem *it; for(uint i=0; icount(); i++) { it=static_cast(l_box->item(i)); if(it && it->account==a) { it=new LBoxItem(a, a->name(), &p_ixmap); l_box->changeItem(it, i); break; } } slotSelectionChanged(); } void KNConfig::NntpAccountListWidget::slotSelectionChanged() { int curr=l_box->currentItem(); d_elBtn->setEnabled(curr!=-1); e_ditBtn->setEnabled(curr!=-1); s_ubBtn->setEnabled(curr!=-1); LBoxItem *it = static_cast(l_box->item(curr)); if(it) { s_erverInfo->setText(i18n("Server: %1").arg(it->account->server())); p_ortInfo->setText(i18n("Port: %1").arg(it->account->port())); } else { s_erverInfo->setText(i18n("Server: ")); p_ortInfo->setText(i18n("Port: ")); } } void KNConfig::NntpAccountListWidget::slotItemSelected(int) { slotEditBtnClicked(); } void KNConfig::NntpAccountListWidget::slotAddBtnClicked() { KNNntpAccount *acc = new KNNntpAccount(); NntpAccountConfDialog *confDlg = new NntpAccountConfDialog(acc, this); if(confDlg->exec()) a_ccManager->newAccount(acc); else delete acc; delete confDlg; } void KNConfig::NntpAccountListWidget::slotDelBtnClicked() { LBoxItem *it = static_cast(l_box->item(l_box->currentItem())); if(it) a_ccManager->removeAccount(it->account); } void KNConfig::NntpAccountListWidget::slotEditBtnClicked() { LBoxItem *it = static_cast(l_box->item(l_box->currentItem())); if(it) { NntpAccountConfDialog *confDlg = new NntpAccountConfDialog(it->account, this); if(confDlg->exec()) a_ccManager->applySettings(it->account); // the account manager will emit accountModified()... delete confDlg; } } void KNConfig::NntpAccountListWidget::slotSubBtnClicked() { LBoxItem *it = static_cast(l_box->item(l_box->currentItem())); if(it) knGlobals.grpManager->showGroupDialog(it->account, this); } //======================================================================================= KNConfig::NntpAccountConfDialog::NntpAccountConfDialog(KNNntpAccount *a, QWidget *p, const char *n) : KDialogBase(Plain, (a->id()!=-1)? i18n("Properties of %1").arg(a->name()):i18n("New Account"), Ok|Cancel|Help, Ok, p, n), a_ccount(a) { QFrame* page=plainPage(); QGridLayout *topL=new QGridLayout(page, 10, 3, 5); n_ame=new QLineEdit(page); QLabel *l=new QLabel(n_ame,i18n("&Name:"),page); topL->addWidget(l, 0,0); n_ame->setText(a->name()); topL->addMultiCellWidget(n_ame, 0, 0, 1, 2); s_erver=new QLineEdit(page); l=new QLabel(s_erver,i18n("&Server:"), page); s_erver->setText(a->server()); topL->addWidget(l, 1,0); topL->addMultiCellWidget(s_erver, 1, 1, 1, 2); p_ort=new QLineEdit(page); l=new QLabel(p_ort, i18n("&Port:"), page); p_ort->setValidator(new KIntValidator(0,65536,this)); p_ort->setText(QString::number(a->port())); topL->addWidget(l, 2,0); topL->addWidget(p_ort, 2,1); h_old = new KIntSpinBox(5,1800,5,5,10,page); l = new QLabel(h_old,i18n("Hol&d connection for:"), page); h_old->setSuffix(i18n(" sec")); h_old->setValue(a->hold()); topL->addWidget(l,3,0); topL->addWidget(h_old,3,1); t_imeout = new KIntSpinBox(15,600,5,15,10,page); l = new QLabel(t_imeout, i18n("&Timeout:"), page); t_imeout->setValue(a->timeout()); t_imeout->setSuffix(i18n(" sec")); topL->addWidget(l,4,0); topL->addWidget(t_imeout,4,1); f_etchDes=new QCheckBox(i18n("&Fetch group descriptions"), page); f_etchDes->setChecked(a->fetchDescriptions()); topL->addMultiCellWidget(f_etchDes, 5,5, 0,3); a_uth=new QCheckBox(i18n("Server requires &authentication"), page); connect(a_uth, SIGNAL(toggled(bool)), this, SLOT(slotAuthChecked(bool))); topL->addMultiCellWidget(a_uth, 6,6, 0,3); u_ser=new QLineEdit(page); u_serLabel=new QLabel(u_ser,i18n("&User:"), page); u_ser->setText(a->user()); topL->addWidget(u_serLabel, 7,0); topL->addMultiCellWidget(u_ser, 7,7, 1,2); p_ass=new QLineEdit(page); p_assLabel=new QLabel(p_ass, i18n("Pass&word:"), page); p_ass->setEchoMode(QLineEdit::Password); p_ass->setText(a->pass()); topL->addWidget(p_assLabel, 8,0); topL->addMultiCellWidget(p_ass, 8,8, 1,2); slotAuthChecked(a->needsLogon()); topL->setColStretch(1, 1); topL->setColStretch(2, 1); setFixedHeight(sizeHint().height()); restoreWindowSize("accNewsPropDLG", this, sizeHint()); setHelp("anc-setting-the-news-account"); } KNConfig::NntpAccountConfDialog::~NntpAccountConfDialog() { saveWindowSize("accNewsPropDLG", size()); } void KNConfig::NntpAccountConfDialog::slotOk() { if (n_ame->text().isEmpty() || s_erver->text().isEmpty()) { KMessageBox::sorry(this, i18n("Please enter an arbitrary name for the account and the\nhostname of the news server.")); return; } a_ccount->setName(n_ame->text()); a_ccount->setServer(s_erver->text()); a_ccount->setPort(p_ort->text().toInt()); a_ccount->setHold(h_old->value()); a_ccount->setTimeout(t_imeout->value()); a_ccount->setFetchDescriptions(f_etchDes->isChecked()); a_ccount->setNeedsLogon(a_uth->isChecked()); a_ccount->setUser(u_ser->text()); a_ccount->setPass(p_ass->text()); accept(); } void KNConfig::NntpAccountConfDialog::slotAuthChecked(bool b) { a_uth->setChecked(b); u_ser->setEnabled(b); u_serLabel->setEnabled(b); p_ass->setEnabled(b); p_assLabel->setEnabled(b); } //============================================================================================= KNConfig::SmtpAccountWidget::SmtpAccountWidget(QWidget *p, const char *n) : BaseWidget(p, n) { QGridLayout *topL=new QGridLayout(this, 5, 3, 5); s_erver=new QLineEdit(this); QLabel *l=new QLabel(s_erver, i18n("&Server:"), this); topL->addWidget(l, 0,0); topL->addMultiCellWidget(s_erver, 0, 0, 1, 2); p_ort=new QLineEdit(this); l=new QLabel(p_ort, i18n("&Port:"), this); topL->addWidget(l, 1,0); p_ort->setValidator(new KIntValidator(0,65536,this)); topL->addWidget(p_ort, 1,1); h_old = new KIntSpinBox(0,300,5,0,10,this); h_old->setSuffix(i18n(" sec")); l = new QLabel(h_old, i18n("Hol&d connection for:"), this); topL->addWidget(l,2,0); topL->addWidget(h_old,2,1); t_imeout = new KIntSpinBox(15,300,5,15,10,this); t_imeout->setSuffix(i18n(" sec")); l = new QLabel(t_imeout, i18n("&Timeout:"), this); topL->addWidget(l,3,0); topL->addWidget(t_imeout,3,1); topL->setColStretch(1,1); topL->setColStretch(2,1); s_erverInfo=knGlobals.accManager->smtp(); s_erver->setText(s_erverInfo->server()); p_ort->setText(QString::number(s_erverInfo->port())); h_old->setValue(s_erverInfo->hold()); t_imeout->setValue(s_erverInfo->timeout()); } KNConfig::SmtpAccountWidget::~SmtpAccountWidget() { } void KNConfig::SmtpAccountWidget::apply() { s_erverInfo->setServer(s_erver->text()); s_erverInfo->setPort(p_ort->text().toInt()); s_erverInfo->setHold(h_old->value()); s_erverInfo->setTimeout(t_imeout->value()); KConfig *conf=KGlobal::config(); conf->setGroup("MAILSERVER"); s_erverInfo->saveConf(conf); } //============================================================================================= //=================================================================================== // code taken from KMail, Copyright (C) 2000 Espen Sand, espen@kde.org KNConfig::AppearanceWidget::ColorListItem::ColorListItem( const QString &text, const QColor &color ) : QListBoxText(text), mColor( color ) { } KNConfig::AppearanceWidget::ColorListItem::~ColorListItem() { } void KNConfig::AppearanceWidget::ColorListItem::paint( QPainter *p ) { QFontMetrics fm = p->fontMetrics(); int h = fm.height(); p->drawText( 30+3*2, fm.ascent() + fm.leading()/2, text() ); p->setPen( Qt::black ); p->drawRect( 3, 1, 30, h-1 ); p->fillRect( 4, 2, 28, h-3, mColor ); } int KNConfig::AppearanceWidget::ColorListItem::height(const QListBox *lb ) const { return( lb->fontMetrics().lineSpacing()+1 ); } int KNConfig::AppearanceWidget::ColorListItem::width(const QListBox *lb ) const { return( 30 + lb->fontMetrics().width( text() ) + 6 ); } //=================================================================================== KNConfig::AppearanceWidget::FontListItem::FontListItem( const QString &name, const QFont &font ) : QListBoxText(name), f_ont(font) { fontInfo = QString("[%1 %2]").arg(f_ont.family()).arg(f_ont.pointSize()); } KNConfig::AppearanceWidget::FontListItem::~FontListItem() { } void KNConfig::AppearanceWidget::FontListItem::setFont(const QFont &font) { f_ont = font; fontInfo = QString("[%1 %2]").arg(f_ont.family()).arg(f_ont.pointSize()); } void KNConfig::AppearanceWidget::FontListItem::paint( QPainter *p ) { QFont fnt = p->font(); fnt.setWeight(QFont::Bold); p->setFont(fnt); int fontInfoWidth = p->fontMetrics().width(fontInfo); int h = p->fontMetrics().ascent() + p->fontMetrics().leading()/2; p->drawText(2, h, fontInfo ); fnt.setWeight(QFont::Normal); p->setFont(fnt); p->drawText(5 + fontInfoWidth, h, text() ); } int KNConfig::AppearanceWidget::FontListItem::width(const QListBox *lb ) const { return( lb->fontMetrics().width(fontInfo) + lb->fontMetrics().width(text()) + 20 ); } //=================================================================================== KNConfig::AppearanceWidget::AppearanceWidget(Appearance *d, QWidget *p, const char *n) : BaseWidget(p, n), d_ata(d) { QGridLayout *topL=new QGridLayout(this, 9,2, 5,5); //long group list l_ongCB = new QCheckBox(i18n("&Show long group list"),this); topL->addWidget(l_ongCB,0,0); //color-list c_List = new QListBox(this); topL->addMultiCellWidget(c_List,2,4,0,0); connect(c_List, SIGNAL(selected(QListBoxItem*)),SLOT(slotColItemSelected(QListBoxItem*))); connect(c_List, SIGNAL(selectionChanged()), SLOT(slotColSelectionChanged())); c_olorCB = new QCheckBox(i18n("&Use custom colors"),this); topL->addWidget(c_olorCB,1,0); connect(c_olorCB, SIGNAL(toggled(bool)), this, SLOT(slotColCheckBoxToggled(bool))); c_olChngBtn=new QPushButton(i18n("Cha&nge"), this); connect(c_olChngBtn, SIGNAL(clicked()), this, SLOT(slotColChangeBtnClicked())); topL->addWidget(c_olChngBtn,2,1); c_olDefBtn=new QPushButton(i18n("&Defaults"), this); connect(c_olDefBtn, SIGNAL(clicked()), this, SLOT(slotColDefaultBtnClicked())); topL->addWidget(c_olDefBtn,3,1); //font-list f_List = new QListBox(this); topL->addMultiCellWidget(f_List,6,8,0,0); connect(f_List, SIGNAL(selected(QListBoxItem*)),SLOT(slotFontItemSelected(QListBoxItem*))); connect(f_List, SIGNAL(selectionChanged()),SLOT(slotFontSelectionChanged())); f_ontCB = new QCheckBox(i18n("Use custom &fonts"),this); topL->addWidget(f_ontCB,5,0); connect(f_ontCB, SIGNAL(toggled(bool)), this, SLOT(slotFontCheckBoxToggled(bool))); f_ntChngBtn=new QPushButton(i18n("Chang&e"), this); connect(f_ntChngBtn, SIGNAL(clicked()), this, SLOT(slotFontChangeBtnClicked())); topL->addWidget(f_ntChngBtn,6,1); f_ntDefBtn=new QPushButton(i18n("Defaul&ts"), this); connect(f_ntDefBtn, SIGNAL(clicked()), this, SLOT(slotFontDefaultBtnClicked())); topL->addWidget(f_ntDefBtn,7,1); //init l_ongCB->setChecked(d->l_ongGroupList); c_olorCB->setChecked(d->u_seColors); slotColCheckBoxToggled(d->u_seColors); for(int i=0; icolorCount(); i++) c_List->insertItem(new ColorListItem(d->colorName(i), d->color(i))); f_ontCB->setChecked(d->u_seFonts); slotFontCheckBoxToggled(d->u_seFonts); for(int i=0; ifontCount(); i++) f_List->insertItem(new FontListItem(d->fontName(i), d->font(i))); } KNConfig::AppearanceWidget::~AppearanceWidget() { } void KNConfig::AppearanceWidget::apply() { if(!d_irty) return; d_ata->l_ongGroupList=l_ongCB->isChecked(); d_ata->u_seColors=c_olorCB->isChecked(); for(int i=0; icolorCount(); i++) d_ata->c_olors[i] = (static_cast(c_List->item(i)))->color(); d_ata->u_seFonts=f_ontCB->isChecked(); for(int i=0; ifontCount(); i++) d_ata->f_onts[i] = (static_cast(f_List->item(i)))->font(); d_ata->save(); } void KNConfig::AppearanceWidget::slotColCheckBoxToggled(bool b) { c_List->setEnabled(b); c_olDefBtn->setEnabled(b); c_olChngBtn->setEnabled(b && (c_List->currentItem()!=-1)); if (b) c_List->setFocus(); } // show color dialog for the entry void KNConfig::AppearanceWidget::slotColItemSelected(QListBoxItem *it) { if (it) { ColorListItem *colorItem = static_cast(it); QColor col = colorItem->color(); int result = KColorDialog::getColor(col,this); if (result == KColorDialog::Accepted) { colorItem->setColor(col); c_List->triggerUpdate(false); } } } void KNConfig::AppearanceWidget::slotColDefaultBtnClicked() { ColorListItem *colorItem; for(int i=0; i < d_ata->colorCount(); i++) { colorItem=static_cast(c_List->item(i)); colorItem->setColor(d_ata->defaultColor(i)); } c_List->triggerUpdate(true); c_List->repaint(true); } void KNConfig::AppearanceWidget::slotColChangeBtnClicked() { if(c_List->currentItem()!=-1) slotColItemSelected(c_List->item(c_List->currentItem())); } void KNConfig::AppearanceWidget::slotColSelectionChanged() { c_olChngBtn->setEnabled(c_List->currentItem()!=-1); } void KNConfig::AppearanceWidget::slotFontCheckBoxToggled(bool b) { f_List->setEnabled(b); f_ntDefBtn->setEnabled(b); f_ntChngBtn->setEnabled(b && (f_List->currentItem()!=-1)); if (b) f_List->setFocus(); } // show font dialog for the entry void KNConfig::AppearanceWidget::slotFontItemSelected(QListBoxItem *it) { if (it) { FontListItem *fontItem = static_cast(it); QFont font = fontItem->font(); int result = KFontDialog::getFont(font,false,this); if (result == KFontDialog::Accepted) { fontItem->setFont(font); f_List->triggerUpdate(false); } } } void KNConfig::AppearanceWidget::slotFontDefaultBtnClicked() { FontListItem *fontItem; for(int i=0; i < d_ata->fontCount(); i++) { fontItem=static_cast(f_List->item(i)); fontItem->setFont(d_ata->defaultFont(i)); } f_List->triggerUpdate(false); } void KNConfig::AppearanceWidget::slotFontChangeBtnClicked() { if(f_List->currentItem()!=-1) slotFontItemSelected(f_List->item(f_List->currentItem())); } void KNConfig::AppearanceWidget::slotFontSelectionChanged() { f_ntChngBtn->setEnabled(f_List->currentItem()!=-1); } //============================================================================================= KNConfig::ReadNewsGeneralWidget::ReadNewsGeneralWidget(ReadNewsGeneral *d, QWidget *p, const char *n) : BaseWidget(p, n), d_ata(d) { - QGroupBox *mgb=new QGroupBox(i18n("Misc"), this); - QGroupBox *vgb=new QGroupBox(i18n("View"), this); + QGroupBox *hgb=new QGroupBox(i18n("Article Handling"), this); + QGroupBox *lgb=new QGroupBox(i18n("Article List"), this); + QLabel *l1; + + a_utoCB=new QCheckBox(i18n("Check for new articles a&utomatically"), hgb); + m_axFetch=new KIntSpinBox(0, 20000, 1, 0, 10, hgb); + l1=new QLabel(m_axFetch, i18n("&Maximal number of articles to fetch"), hgb); + m_arkCB=new QCheckBox(i18n("Mar&k article as read after"), hgb); + m_arkSecs=new KIntSpinBox(0, 9999, 1, 0, 10, hgb); + connect(m_arkCB, SIGNAL(toggled(bool)), m_arkSecs, SLOT(setEnabled(bool))); + m_arkSecs->setSuffix(i18n(" sec")); + + e_xpThrCB=new QCheckBox(i18n("Show &whole thread on expanding"), lgb); + s_coreCB=new QCheckBox(i18n("Show article &score"), lgb); + l_inesCB=new QCheckBox(i18n("Show &line count"), lgb); + + QVBoxLayout *topL=new QVBoxLayout(this, 5); + QGridLayout *hgbL=new QGridLayout(hgb, 4,2, 8,5); + QVBoxLayout *lgbL=new QVBoxLayout(lgb, 8, 5); + + topL->addWidget(hgb); + topL->addWidget(lgb); + topL->addStretch(1); + + hgbL->addRowSpacing(0, fontMetrics().lineSpacing()-4); + hgbL->addWidget(a_utoCB, 1,0); + hgbL->addWidget(l1, 2, 0); + hgbL->addWidget(m_axFetch, 2,1); + hgbL->addWidget(m_arkCB, 3,0); + hgbL->addWidget(m_arkSecs, 3,1); + hgbL->setColStretch(0,1); + + lgbL->addSpacing(fontMetrics().lineSpacing()-4); + lgbL->addWidget(e_xpThrCB); + lgbL->addWidget(s_coreCB); + lgbL->addWidget(l_inesCB); + + topL->setResizeMode(QLayout::Minimum); + + //init + a_utoCB->setChecked(d->a_utoCheck); + m_axFetch->setValue(d->m_axFetch); + m_arkCB->setChecked(d->a_utoMark); + m_arkSecs->setValue(d->m_arkSecs); + m_arkSecs->setEnabled(d->a_utoMark); + e_xpThrCB->setChecked(d->t_otalExpand); + l_inesCB->setChecked(d->s_howLines); + s_coreCB->setChecked(d->s_howScore); +} + + +KNConfig::ReadNewsGeneralWidget::~ReadNewsGeneralWidget() +{ +} + + +void KNConfig::ReadNewsGeneralWidget::apply() +{ + if(!d_irty) + return; + + d_ata->a_utoCheck=a_utoCB->isChecked(); + d_ata->m_axFetch=m_axFetch->value(); + d_ata->a_utoMark=m_arkCB->isChecked(); + d_ata->m_arkSecs=m_arkSecs->value(); + d_ata->t_otalExpand=e_xpThrCB->isChecked(); + d_ata->s_howLines=l_inesCB->isChecked(); + d_ata->s_howScore=s_coreCB->isChecked(); + + d_ata->save(); +} + + +//============================================================================================= + + +KNConfig::ReadNewsViewerWidget::ReadNewsViewerWidget(ReadNewsViewer *d, QWidget *p, const char *n) + : BaseWidget(p, n), d_ata(d) +{ + QGroupBox *appgb=new QGroupBox(i18n("Appearance"), this); QGroupBox *agb=new QGroupBox(i18n("Attachments"), this); QGroupBox *bgb=new QGroupBox(i18n("Browser"), this); - QLabel *l1,*l3; - - a_utoCB=new QCheckBox(i18n("Check for new articles a&utomatically"), mgb); - m_axFetch=new KIntSpinBox(0, 20000, 1, 0, 10, mgb); - l1=new QLabel(m_axFetch, i18n("&Maximal number of articles to fetch"), mgb); - m_arkCB=new QCheckBox(i18n("Mar&k article as read after"), mgb); - m_arkSecs=new KIntSpinBox(0, 9999, 1, 0, 10, mgb); - connect(m_arkCB, SIGNAL(toggled(bool)), SLOT(slotMarkReadToggled(bool))); - m_arkSecs->setSuffix(i18n(" sec")); - e_xpThrCB=new QCheckBox(i18n("Show &whole thread on expanding"), vgb); - s_igCB=new QCheckBox(i18n("Show sig&nature"), vgb); - f_ormatCB=new QCheckBox(i18n("Interpret te&xt format tags"), vgb); + QLabel *l1; + + s_igCB=new QCheckBox(i18n("Show sig&nature"), appgb); + f_ormatCB=new QCheckBox(i18n("Interpret te&xt format tags"), appgb); i_nlineCB=new QCheckBox(i18n("Show attachments &inline if possible"), agb); o_penAttCB=new QCheckBox(i18n("Open a&ttachments on click"), agb); a_ltAttCB=new QCheckBox(i18n("Show alternati&ve contents as attachments"), agb); + b_rowser=new QComboBox(bgb); b_rowser->insertItem("Konqueror"); b_rowser->insertItem("Netscape"); b_rowser->insertItem("Mozilla"); b_rowser->insertItem("Opera"); b_rowser->insertItem("Other"); connect(b_rowser, SIGNAL(activated(int)), SLOT(slotBrowserTypeChanged(int))); - l3=new QLabel(b_rowser, i18n("Open &links with"), bgb); + l1=new QLabel(b_rowser, i18n("Open &links with"), bgb); b_rowserCommand = new QLineEdit(bgb); c_hooseBrowser= new QPushButton(i18n("Choo&se..."),bgb); connect(c_hooseBrowser, SIGNAL(clicked()), SLOT(slotChooseBrowser())); QVBoxLayout *topL=new QVBoxLayout(this, 5); - QGridLayout *mgbL=new QGridLayout(mgb, 4,2, 8,5); - QVBoxLayout *vgbL=new QVBoxLayout(vgb, 8, 5); + QVBoxLayout *appgbL=new QVBoxLayout(appgb, 8, 5); QVBoxLayout *agbL=new QVBoxLayout(agb, 8, 5); QGridLayout *bgbL=new QGridLayout(bgb, 3,3, 8,5); - topL->addWidget(mgb); - topL->addWidget(vgb); + topL->addWidget(appgb); topL->addWidget(agb); topL->addWidget(bgb); topL->addStretch(1); - mgbL->addRowSpacing(0, fontMetrics().lineSpacing()-4); - mgbL->addWidget(a_utoCB, 1,0); - mgbL->addWidget(l1, 2, 0); - mgbL->addWidget(m_axFetch, 2,1); - mgbL->addWidget(m_arkCB, 3,0); - mgbL->addWidget(m_arkSecs, 3,1); - mgbL->setColStretch(0,1); - vgbL->addSpacing(fontMetrics().lineSpacing()-4); - vgbL->addWidget(e_xpThrCB); - vgbL->addWidget(s_igCB); - vgbL->addWidget(f_ormatCB); + + appgbL->addSpacing(fontMetrics().lineSpacing()-4); + appgbL->addWidget(s_igCB); + appgbL->addWidget(f_ormatCB); + agbL->addSpacing(fontMetrics().lineSpacing()-4); agbL->addWidget(i_nlineCB); agbL->addWidget(o_penAttCB); agbL->addWidget(a_ltAttCB); + bgbL->addRowSpacing(0, fontMetrics().lineSpacing()-4); - bgbL->addWidget(l3, 1,0); + bgbL->addWidget(l1, 1,0); bgbL->addMultiCellWidget(b_rowser,1,1,1,2); bgbL->addMultiCellWidget(b_rowserCommand,2,2,0,1); bgbL->addWidget(c_hooseBrowser,2,2); bgbL->setColStretch(1,1); + topL->setResizeMode(QLayout::Minimum); //init - a_utoCB->setChecked(d->a_utoCheck); - m_arkCB->setChecked(d->a_utoMark); - b_rowser->setCurrentItem((int)(d->b_rowser)); - b_rowserCommand->setText(d->b_rowserCommand); - b_rowserCommand->setEnabled(d->b_rowser==ReadNewsGeneral::BTother); - c_hooseBrowser->setEnabled(d->b_rowser==ReadNewsGeneral::BTother); + s_igCB->setChecked(d->s_howSig); + f_ormatCB->setChecked(d->i_nterpretFormatTags); i_nlineCB->setChecked(d->i_nlineAtt); o_penAttCB->setChecked(d->o_penAtt); a_ltAttCB->setChecked(d->s_howAlts); - s_igCB->setChecked(d->s_howSig); - f_ormatCB->setChecked(d->i_nterpretFormatTags); - e_xpThrCB->setChecked(d->t_otalExpand); - m_axFetch->setValue(d->m_axFetch); - m_arkSecs->setValue(d->m_arkSecs); + b_rowser->setCurrentItem((int)(d->b_rowser)); + b_rowserCommand->setText(d->b_rowserCommand); + b_rowserCommand->setEnabled(d->b_rowser==ReadNewsViewer::BTother); + c_hooseBrowser->setEnabled(d->b_rowser==ReadNewsViewer::BTother); } -KNConfig::ReadNewsGeneralWidget::~ReadNewsGeneralWidget() +KNConfig::ReadNewsViewerWidget::~ReadNewsViewerWidget() { } -void KNConfig::ReadNewsGeneralWidget::apply() +void KNConfig::ReadNewsViewerWidget::apply() { if(!d_irty) return; - d_ata->a_utoCheck=a_utoCB->isChecked(); d_ata->s_howSig=s_igCB->isChecked(); d_ata->i_nterpretFormatTags=f_ormatCB->isChecked(); - d_ata->t_otalExpand=e_xpThrCB->isChecked(); - d_ata->m_axFetch=m_axFetch->value(); - d_ata->a_utoMark=m_arkCB->isChecked(); - d_ata->m_arkSecs=m_arkSecs->value(); d_ata->i_nlineAtt=i_nlineCB->isChecked(); d_ata->o_penAtt=o_penAttCB->isChecked(); d_ata->s_howAlts=a_ltAttCB->isChecked(); - d_ata->b_rowser=(ReadNewsGeneral::browserType)(b_rowser->currentItem()); + d_ata->b_rowser=(ReadNewsViewer::browserType)(b_rowser->currentItem()); d_ata->b_rowserCommand=b_rowserCommand->text(); d_ata->save(); } -void KNConfig::ReadNewsGeneralWidget::slotMarkReadToggled(bool b) -{ - m_arkSecs->setEnabled(b); - if (b) m_arkSecs->setFocus(); -} - - -void KNConfig::ReadNewsGeneralWidget::slotBrowserTypeChanged(int i) +void KNConfig::ReadNewsViewerWidget::slotBrowserTypeChanged(int i) { - bool enabled=((ReadNewsGeneral::browserType)(i)==ReadNewsGeneral::BTother); + bool enabled=((ReadNewsViewer::browserType)(i)==ReadNewsViewer::BTother); b_rowserCommand->setEnabled(enabled); c_hooseBrowser->setEnabled(enabled); } -void KNConfig::ReadNewsGeneralWidget::slotChooseBrowser() +void KNConfig::ReadNewsViewerWidget::slotChooseBrowser() { QString path=b_rowserCommand->text().simplifyWhiteSpace(); if (path.right(3) == " %u") path.truncate(path.length()-3); path=KFileDialog::getOpenFileName(path, QString::null, this, i18n("Choose Browser")); if (!path.isEmpty()) b_rowserCommand->setText(path+" %u"); } //============================================================================================= KNConfig::DisplayedHeadersWidget::DisplayedHeadersWidget(DisplayedHeaders *d, QWidget *p, const char *n) : BaseWidget(p, n), s_ave(false), d_ata(d) { QGridLayout *topL=new QGridLayout(this, 7,2, 5,5); //listbox l_box=new QListBox(this); connect(l_box, SIGNAL(selected(int)), this, SLOT(slotItemSelected(int))); connect(l_box, SIGNAL(selectionChanged()), this, SLOT(slotSelectionChanged())); topL->addMultiCellWidget(l_box, 0,6, 0,0); // buttons a_ddBtn=new QPushButton(i18n("&New"), this); connect(a_ddBtn, SIGNAL(clicked()), this, SLOT(slotAddBtnClicked())); topL->addWidget(a_ddBtn, 0,1); d_elBtn=new QPushButton(i18n("&Delete"), this); connect(d_elBtn, SIGNAL(clicked()), this, SLOT(slotDelBtnClicked())); topL->addWidget(d_elBtn, 1,1); e_ditBtn=new QPushButton(i18n("modify something","&Edit"), this); connect(e_ditBtn, SIGNAL(clicked()), this, SLOT(slotEditBtnClicked())); topL->addWidget(e_ditBtn, 2,1); u_pBtn=new QPushButton(i18n("&Up"), this); connect(u_pBtn, SIGNAL(clicked()), this, SLOT(slotUpBtnClicked())); topL->addWidget(u_pBtn, 4,1); d_ownBtn=new QPushButton(i18n("Do&wn"), this); connect(d_ownBtn, SIGNAL(clicked()), this, SLOT(slotDownBtnClicked())); topL->addWidget(d_ownBtn, 5,1); topL->addRowSpacing(3,20); // separate up/down buttons topL->setRowStretch(6,1); // stretch the listbox for(KNDisplayedHeader *h=d->h_drList.first(); h; h=d->h_drList.next()) l_box->insertItem(generateItem(h)); slotSelectionChanged(); // disable buttons initially } KNConfig::DisplayedHeadersWidget::~DisplayedHeadersWidget() { if(s_ave) d_ata->save(); } KNConfig::DisplayedHeadersWidget::HdrItem* KNConfig::DisplayedHeadersWidget::generateItem(KNDisplayedHeader *h) { QString text; if(h->hasName()) { text=h->translatedName(); text+=": <"; } else text="<"; text+=h->header(); text+=">"; return new HdrItem(text,h); } void KNConfig::DisplayedHeadersWidget::slotItemSelected(int) { slotEditBtnClicked(); } void KNConfig::DisplayedHeadersWidget::slotSelectionChanged() { int curr = l_box->currentItem(); d_elBtn->setEnabled(curr!=-1); e_ditBtn->setEnabled(curr!=-1); u_pBtn->setEnabled(curr>0); d_ownBtn->setEnabled((curr!=-1)&&(curr+1!=(int)(l_box->count()))); } void KNConfig::DisplayedHeadersWidget::slotAddBtnClicked() { KNDisplayedHeader *h=d_ata->createNewHeader(); DisplayedHeaderConfDialog* dlg=new DisplayedHeaderConfDialog(h, this); if(dlg->exec()) { l_box->insertItem(generateItem(h)); h->createTags(); s_ave=true; } else d_ata->remove(h); } void KNConfig::DisplayedHeadersWidget::slotDelBtnClicked() { if(l_box->currentItem()==-1) return; if(KMessageBox::questionYesNo(this, i18n("Really delete this header?"))==KMessageBox::Yes) { KNDisplayedHeader *h = (static_cast(l_box->item(l_box->currentItem())))->hdr; d_ata->remove(h); l_box->removeItem(l_box->currentItem()); s_ave=true; } } void KNConfig::DisplayedHeadersWidget::slotEditBtnClicked() { if (l_box->currentItem()==-1) return; KNDisplayedHeader *h = (static_cast(l_box->item(l_box->currentItem())))->hdr; DisplayedHeaderConfDialog* dlg=new DisplayedHeaderConfDialog(h, this); if(dlg->exec()) { l_box->changeItem(generateItem(h), l_box->currentItem()); h->createTags(); s_ave=true; } } void KNConfig::DisplayedHeadersWidget::slotUpBtnClicked() { int c=l_box->currentItem(); if(c==0 || c==-1) return; KNDisplayedHeader *h = (static_cast(l_box->item(c)))->hdr; d_ata->up(h); l_box->insertItem(generateItem(h), c-1); l_box->removeItem(c+1); l_box->setCurrentItem(c-1); s_ave=true; } void KNConfig::DisplayedHeadersWidget::slotDownBtnClicked() { int c=l_box->currentItem(); if(c==-1 || c==(int) l_box->count()-1) return; KNDisplayedHeader *h = (static_cast(l_box->item(c)))->hdr; d_ata->down(h); l_box->insertItem(generateItem(h), c+2); l_box->removeItem(c); l_box->setCurrentItem(c+1); s_ave=true; } //============================================================================================= KNConfig::DisplayedHeaderConfDialog::DisplayedHeaderConfDialog(KNDisplayedHeader *h, QWidget *p, char *n) : KDialogBase(Plain, i18n("Header Properties"),Ok|Cancel|Help, Ok, p, n), h_dr(h) { QFrame* page=plainPage(); QGridLayout *topL=new QGridLayout(page, 2, 2, 0, 5); QWidget *nameW = new QWidget(page); QGridLayout *nameL=new QGridLayout(nameW, 2, 2, 5); h_drC=new QComboBox(true, nameW); h_drC->lineEdit()->setMaxLength(64); connect(h_drC, SIGNAL(activated(int)), this, SLOT(slotActivated(int))); nameL->addWidget(new QLabel(h_drC, i18n("H&eader:"),nameW),0,0); nameL->addWidget(h_drC,0,1); n_ameE=new QLineEdit(nameW); connect(n_ameE, SIGNAL(textChanged(const QString&)), SLOT(slotNameChanged(const QString&))); n_ameE->setMaxLength(64); nameL->addWidget(new QLabel(n_ameE, i18n("Displayed Na&me:"),nameW),1,0); nameL->addWidget(n_ameE,1,1); nameL->setColStretch(1,1); topL->addMultiCellWidget(nameW,0,0,0,1); QGroupBox *ngb=new QGroupBox(i18n("Name"), page); QVBoxLayout *ngbL = new QVBoxLayout(ngb, 8, 5); ngbL->setAutoAdd(true); ngbL->addSpacing(fontMetrics().lineSpacing()-4); n_ameCB[0]=new QCheckBox(i18n("&large"), ngb); n_ameCB[1]=new QCheckBox(i18n("&bold"), ngb); n_ameCB[2]=new QCheckBox(i18n("&italic"), ngb); n_ameCB[3]=new QCheckBox(i18n("&underlined"), ngb); topL->addWidget(ngb,1,0); QGroupBox *vgb=new QGroupBox(i18n("Value"), page); QVBoxLayout *vgbL = new QVBoxLayout(vgb, 8, 5); vgbL->setAutoAdd(true); vgbL->addSpacing(fontMetrics().lineSpacing()-4); v_alueCB[0]=new QCheckBox(i18n("l&arge"), vgb); v_alueCB[1]=new QCheckBox(i18n("bol&d"), vgb); v_alueCB[2]=new QCheckBox(i18n("i&talic"), vgb); v_alueCB[3]=new QCheckBox(i18n("u&nderlined"), vgb); topL->addWidget(vgb,1,1); topL->setColStretch(0,1); topL->setColStretch(1,1); // preset values... h_drC->insertStrList(KNDisplayedHeader::predefs()); h_drC->lineEdit()->setText(h->header()); n_ameE->setText(h->translatedName()); for(int i=0; i<4; i++) { n_ameCB[i]->setChecked(h->flag(i)); v_alueCB[i]->setChecked(h->flag(i+4)); } setFixedHeight(sizeHint().height()); restoreWindowSize("accReadHdrPropDLG", this, sizeHint()); setHelp("anc-knode-headers"); } KNConfig::DisplayedHeaderConfDialog::~DisplayedHeaderConfDialog() { saveWindowSize("accReadHdrPropDLG", size()); } void KNConfig::DisplayedHeaderConfDialog::slotOk() { h_dr->setHeader(h_drC->currentText()); h_dr->setTranslatedName(n_ameE->text()); for(int i=0; i<4; i++) { if(h_dr->hasName()) h_dr->setFlag(i, n_ameCB[i]->isChecked()); else h_dr->setFlag(i,false); h_dr->setFlag(i+4, v_alueCB[i]->isChecked()); } accept(); } // the user selected one of the presets, insert the *translated* string as display name: void KNConfig::DisplayedHeaderConfDialog::slotActivated(int pos) { n_ameE->setText(i18n(h_drC->text(pos).local8Bit())); // I think it's save here, the combobox has only english defaults } // disable the name format options when the name is empty void KNConfig::DisplayedHeaderConfDialog::slotNameChanged(const QString& str) { for(int i=0; i<4; i++) n_ameCB[i]->setEnabled(!str.isEmpty()); } //============================================================================================= KNConfig::FilterListWidget::FilterListWidget(QWidget *p, const char *n) : BaseWidget(p,n), f_ilManager(knGlobals.filManager) { QGridLayout *topL=new QGridLayout(this, 6,2, 5,5); // == Filters ================================================= f_lb=new QListBox(this); topL->addWidget(new QLabel(f_lb, i18n("&Filters:"),this),0,0); connect(f_lb, SIGNAL(selectionChanged()), SLOT(slotSelectionChangedFilter())); connect(f_lb, SIGNAL(selected(int)), SLOT(slotItemSelectedFilter(int))); topL->addMultiCellWidget(f_lb,1,5,0,0); a_ddBtn=new QPushButton(i18n("&New"), this); connect(a_ddBtn, SIGNAL(clicked()), this, SLOT(slotAddBtnClicked())); topL->addWidget(a_ddBtn,1,1); d_elBtn=new QPushButton(i18n("&Delete"), this); connect(d_elBtn, SIGNAL(clicked()), this, SLOT(slotDelBtnClicked())); topL->addWidget(d_elBtn,2,1); e_ditBtn=new QPushButton(i18n("modify something","&Edit"), this); connect(e_ditBtn, SIGNAL(clicked()), this, SLOT(slotEditBtnClicked())); topL->addWidget(e_ditBtn,3,1); c_opyBtn=new QPushButton(i18n("Co&py"), this); connect(c_opyBtn, SIGNAL(clicked()), this, SLOT(slotCopyBtnClicked())); topL->addWidget(c_opyBtn,4,1); // == Menu ==================================================== m_lb=new QListBox(this); topL->addWidget(new QLabel(m_lb, i18n("&Menu:"),this),6,0); connect(m_lb, SIGNAL(selectionChanged()), SLOT(slotSelectionChangedMenu())); topL->addMultiCellWidget(m_lb,7,11,0,0); u_pBtn=new QPushButton(i18n("&Up"), this); connect(u_pBtn, SIGNAL(clicked()), this, SLOT(slotUpBtnClicked())); topL->addWidget(u_pBtn,7,1); d_ownBtn=new QPushButton(i18n("Do&wn"), this); connect(d_ownBtn, SIGNAL(clicked()), this, SLOT(slotDownBtnClicked())); topL->addWidget(d_ownBtn,8,1); s_epAddBtn=new QPushButton(i18n("Add\n&Separator"), this); connect(s_epAddBtn, SIGNAL(clicked()), this, SLOT(slotSepAddBtnClicked())); topL->addWidget(s_epAddBtn,9,1); s_epRemBtn=new QPushButton(i18n("&Remove\nSeparator"), this); connect(s_epRemBtn, SIGNAL(clicked()), this, SLOT(slotSepRemBtnClicked())); topL->addWidget(s_epRemBtn,10,1); topL->setRowStretch(5,1); topL->setRowStretch(11,1); a_ctive = SmallIcon("filter",16); d_isabled = SmallIcon("filter",16,KIcon::DisabledState); f_ilManager->startConfig(this); slotSelectionChangedFilter(); slotSelectionChangedMenu(); } KNConfig::FilterListWidget::~FilterListWidget() { f_ilManager->endConfig(); } void KNConfig::FilterListWidget::apply() { if(d_irty) f_ilManager->commitChanges(); } void KNConfig::FilterListWidget::addItem(KNArticleFilter *f) { if(f->isEnabled()) f_lb->insertItem(new LBoxItem(f, f->translatedName(), &a_ctive)); else f_lb->insertItem(new LBoxItem(f, f->translatedName(), &d_isabled)); slotSelectionChangedFilter(); } void KNConfig::FilterListWidget::removeItem(KNArticleFilter *f) { int i=findItem(f_lb, f); if (i!=-1) f_lb->removeItem(i); slotSelectionChangedFilter(); } void KNConfig::FilterListWidget::updateItem(KNArticleFilter *f) { int i=findItem(f_lb, f); if(i!=-1) { if(f->isEnabled()) { f_lb->changeItem(new LBoxItem(f, f->translatedName(), &a_ctive), i); m_lb->changeItem(new LBoxItem(f, f->translatedName()), findItem(m_lb, f)); } else f_lb->changeItem(new LBoxItem(f, f->translatedName(), &d_isabled), i); } slotSelectionChangedFilter(); } void KNConfig::FilterListWidget::addMenuItem(KNArticleFilter *f) { if (f) { if (findItem(m_lb, f)==-1) m_lb->insertItem(new LBoxItem(f, f->translatedName())); } else // separator m_lb->insertItem(new LBoxItem(0, "===")); slotSelectionChangedMenu(); } void KNConfig::FilterListWidget::removeMenuItem(KNArticleFilter *f) { int i=findItem(m_lb, f); if(i!=-1) m_lb->removeItem(i); slotSelectionChangedMenu(); } QValueList KNConfig::FilterListWidget::menuOrder() { KNArticleFilter *f; QValueList lst; for(uint i=0; icount(); i++) { f= (static_cast(m_lb->item(i)))->filter; if(f) lst << f->id(); else lst << -1; } return lst; } int KNConfig::FilterListWidget::findItem(QListBox *l, KNArticleFilter *f) { int idx=0; bool found=false; while(!found && idx < (int) l->count()) { found=( (static_cast(l->item(idx)))->filter==f ); if(!found) idx++; } if(found) return idx; else return -1; } void KNConfig::FilterListWidget::slotAddBtnClicked() { f_ilManager->newFilter(); } void KNConfig::FilterListWidget::slotDelBtnClicked() { if (f_lb->currentItem()!=-1) f_ilManager->deleteFilter( (static_cast(f_lb->item(f_lb->currentItem())))->filter ); } void KNConfig::FilterListWidget::slotEditBtnClicked() { if (f_lb->currentItem()!=-1) f_ilManager->editFilter( (static_cast(f_lb->item(f_lb->currentItem())))->filter ); } void KNConfig::FilterListWidget::slotCopyBtnClicked() { if (f_lb->currentItem()!=-1) f_ilManager->copyFilter( (static_cast(f_lb->item(f_lb->currentItem())))->filter ); } void KNConfig::FilterListWidget::slotUpBtnClicked() { int c=m_lb->currentItem(); KNArticleFilter *f=0; if(c==0 || c==-1) return; f=(static_cast(m_lb->item(c)))->filter; if(f) m_lb->insertItem(new LBoxItem(f, f->translatedName()), c-1); else m_lb->insertItem(new LBoxItem(0, "==="), c-1); m_lb->removeItem(c+1); m_lb->setCurrentItem(c-1); } void KNConfig::FilterListWidget::slotDownBtnClicked() { int c=m_lb->currentItem(); KNArticleFilter *f=0; if(c==-1 || c+1==(int)m_lb->count()) return; f=(static_cast(m_lb->item(c)))->filter; if(f) m_lb->insertItem(new LBoxItem(f, f->translatedName()), c+2); else m_lb->insertItem(new LBoxItem(0, "==="), c+2); m_lb->removeItem(c); m_lb->setCurrentItem(c+1); } void KNConfig::FilterListWidget::slotSepAddBtnClicked() { m_lb->insertItem(new LBoxItem(0, "==="), m_lb->currentItem()); slotSelectionChangedMenu(); } void KNConfig::FilterListWidget::slotSepRemBtnClicked() { int c=m_lb->currentItem(); if( (c!=-1) && ( (static_cast(m_lb->item(c)))->filter==0 ) ) m_lb->removeItem(c); slotSelectionChangedMenu(); } void KNConfig::FilterListWidget::slotItemSelectedFilter(int) { slotEditBtnClicked(); } void KNConfig::FilterListWidget::slotSelectionChangedFilter() { int curr = f_lb->currentItem(); d_elBtn->setEnabled(curr!=-1); e_ditBtn->setEnabled(curr!=-1); c_opyBtn->setEnabled(curr!=-1); } void KNConfig::FilterListWidget::slotSelectionChangedMenu() { int curr = m_lb->currentItem(); u_pBtn->setEnabled(curr>0); d_ownBtn->setEnabled((curr!=-1)&&(curr+1!=(int)m_lb->count())); s_epRemBtn->setEnabled((curr!=-1) && ( (static_cast(m_lb->item(curr)))->filter==0 ) ); } //============================================================================================= KNConfig::PostNewsTechnicalWidget::PostNewsTechnicalWidget(PostNewsTechnical *d, QWidget *p, const char *n) : BaseWidget(p, n), d_ata(d) { QVBoxLayout *topL=new QVBoxLayout(this, 5); // ==== General ============================================================= QGroupBox *ggb=new QGroupBox(i18n("General"), this); QGridLayout *ggbL=new QGridLayout(ggb, 7,2, 8,5); topL->addWidget(ggb); ggbL->addRowSpacing(0, fontMetrics().lineSpacing()-4); c_harset=new QComboBox(ggb); c_harset->insertStringList(d->composerCharsets()); ggbL->addWidget(new QLabel(c_harset, i18n("Cha&rset"), ggb), 1,0); ggbL->addWidget(c_harset, 1,1); e_ncoding=new QComboBox(ggb); e_ncoding->insertItem("Allow 8-bit"); e_ncoding->insertItem("7-bit (Quoted-Printable)"); ggbL->addWidget(new QLabel(e_ncoding, i18n("Enco&ding"), ggb), 2,0); ggbL->addWidget(e_ncoding, 2,1); u_seOwnCSCB=new QCheckBox(i18n("Use o&wn default charset when replying"), ggb); ggbL->addMultiCellWidget(u_seOwnCSCB, 3,3, 0,1); a_llow8bitCB=new QCheckBox(i18n("Don't encode &8-bit characters in the header"), ggb); connect(a_llow8bitCB, SIGNAL(toggled(bool)), this, SLOT(slotHeadEncToggled(bool))); ggbL->addMultiCellWidget(a_llow8bitCB, 4,4, 0,1); g_enMIdCB=new QCheckBox(i18n("&Generate Message-Id"), ggb); connect(g_enMIdCB, SIGNAL(toggled(bool)), this, SLOT(slotGenMIdCBToggled(bool))); ggbL->addMultiCellWidget(g_enMIdCB, 5,5, 0,1); h_ost=new QLineEdit(ggb); h_ost->setEnabled(false); h_ostL=new QLabel(h_ost, i18n("Ho&stname:"), ggb); h_ostL->setEnabled(false); ggbL->addWidget(h_ostL, 6,0); ggbL->addWidget(h_ost, 6,1); ggbL->setColStretch(1,1); // ==== X-Headers ============================================================= QGroupBox *xgb=new QGroupBox(i18n("X-Headers"), this); topL->addWidget(xgb, 1); QGridLayout *xgbL=new QGridLayout(xgb, 6,2, 8,5); xgbL->addRowSpacing(0, fontMetrics().lineSpacing()-4); l_box=new QListBox(xgb); connect(l_box, SIGNAL(selected(int)), SLOT(slotItemSelected(int))); connect(l_box, SIGNAL(selectionChanged()), SLOT(slotSelectionChanged())); xgbL->addMultiCellWidget(l_box, 1,4, 0,0); a_ddBtn=new QPushButton(i18n("&New"), xgb); connect(a_ddBtn, SIGNAL(clicked()), SLOT(slotAddBtnClicked())); xgbL->addWidget(a_ddBtn, 1,1); d_elBtn=new QPushButton(i18n("Dele&te"), xgb); connect(d_elBtn, SIGNAL(clicked()), SLOT(slotDelBtnClicked())); xgbL->addWidget(d_elBtn, 2,1); e_ditBtn=new QPushButton(i18n("modify something","&Edit"), xgb); connect(e_ditBtn, SIGNAL(clicked()), SLOT(slotEditBtnClicked())); xgbL->addWidget(e_ditBtn, 3,1); i_ncUaCB=new QCheckBox(i18n("Don't add the \"&User-Agent\" identification header"), xgb); xgbL->addMultiCellWidget(i_ncUaCB, 5,5, 0,1); xgbL->setRowStretch(4,1); xgbL->setColStretch(0,1); //init c_harset->setCurrentItem(d->indexForCharset(d->charset())); e_ncoding->setCurrentItem(d->a_llow8BitBody? 0:1); u_seOwnCSCB->setChecked(d->u_seOwnCharset); a_llow8bitCB->blockSignals(true); //avoid warning message on startup a_llow8bitCB->setChecked(d->a_llow8BitHeaders); a_llow8bitCB->blockSignals(false); g_enMIdCB->setChecked(d->g_enerateMID); h_ost->setText(d->h_ostname); i_ncUaCB->setChecked(d->d_ontIncludeUA); for(XHeaders::Iterator it=d->x_headers.begin(); it!=d->x_headers.end(); ++it) l_box->insertItem((*it).header()); slotSelectionChanged(); } KNConfig::PostNewsTechnicalWidget::~PostNewsTechnicalWidget() { } void KNConfig::PostNewsTechnicalWidget::apply() { if(!d_irty) return; d_ata->c_harset=c_harset->currentText().latin1(); d_ata->a_llow8BitBody=(e_ncoding->currentItem()==0); d_ata->u_seOwnCharset=u_seOwnCSCB->isChecked(); d_ata->a_llow8BitHeaders=a_llow8bitCB->isChecked(); d_ata->g_enerateMID=g_enMIdCB->isChecked(); d_ata->h_ostname=h_ost->text().latin1(); d_ata->d_ontIncludeUA=i_ncUaCB->isChecked(); d_ata->x_headers.clear(); for(unsigned int idx=0; idxcount(); idx++) d_ata->x_headers.append( XHeader(l_box->text(idx)) ); d_ata->save(); } void KNConfig::PostNewsTechnicalWidget::slotHeadEncToggled(bool b) { if (b) KMessageBox::information(this,i18n("Please be aware that unencoded 8-bit characters\nare illegal in the header of a usenet message.\nUse this feature with extreme care!")); } void KNConfig::PostNewsTechnicalWidget::slotGenMIdCBToggled(bool b) { h_ost->setEnabled(b); h_ostL->setEnabled(b); } void KNConfig::PostNewsTechnicalWidget::slotSelectionChanged() { d_elBtn->setEnabled(l_box->currentItem()!=-1); e_ditBtn->setEnabled(l_box->currentItem()!=-1); } void KNConfig::PostNewsTechnicalWidget::slotItemSelected(int) { slotEditBtnClicked(); } void KNConfig::PostNewsTechnicalWidget::slotAddBtnClicked() { XHeaderConfDialog *dlg=new XHeaderConfDialog(QString::null, this); if (dlg->exec()) l_box->insertItem(dlg->result()); delete dlg; slotSelectionChanged(); } void KNConfig::PostNewsTechnicalWidget::slotDelBtnClicked() { int c=l_box->currentItem(); if (c == -1) return; l_box->removeItem(c); slotSelectionChanged(); } void KNConfig::PostNewsTechnicalWidget::slotEditBtnClicked() { int c=l_box->currentItem(); if (c == -1) return; XHeaderConfDialog *dlg=new XHeaderConfDialog(l_box->text(c), this); if (dlg->exec()) l_box->changeItem(dlg->result(),c); delete dlg; slotSelectionChanged(); } //=================================================================================================== KNConfig::XHeaderConfDialog::XHeaderConfDialog(const QString &h, QWidget *p, const char *n) : KDialogBase(Plain, i18n("X-Headers"),Ok|Cancel, Ok, p, n) { QFrame* page=plainPage(); QHBoxLayout *topL=new QHBoxLayout(page, 5,8); topL->setAutoAdd(true); new QLabel("X-", page); n_ame=new QLineEdit(page); new QLabel(":", page); v_alue=new QLineEdit(page); int pos=h.find(": ", 2); if(pos!=-1) { n_ame->setText(h.mid(2, pos-2)); pos+=2; v_alue->setText(h.mid(pos, h.length()-pos)); } setFixedHeight(sizeHint().height()); restoreWindowSize("XHeaderDlg", this, sizeHint()); n_ame->setFocus(); } KNConfig::XHeaderConfDialog::~XHeaderConfDialog() { saveWindowSize("XHeaderDlg", size()); } QString KNConfig::XHeaderConfDialog::result() { return QString("X-%1: %2").arg(n_ame->text()).arg(v_alue->text()); } //=================================================================================================== KNConfig::PostNewsComposerWidget::PostNewsComposerWidget(PostNewsComposer *d, QWidget *p, const char *n) : BaseWidget(p, n), d_ata(d) { QVBoxLayout *topL=new QVBoxLayout(this, 5); // === general =========================================================== QGroupBox *generalB=new QGroupBox(i18n("General"), this); topL->addWidget(generalB); QGridLayout *generalL=new QGridLayout(generalB, 3,3, 8,5); generalL->addRowSpacing(0, fontMetrics().lineSpacing()-4); w_ordWrapCB=new QCheckBox(i18n("Word &wrap at column:"), generalB); generalL->addWidget(w_ordWrapCB,1,0); m_axLen=new KIntSpinBox(20, 200, 1, 20, 10, generalB); generalL->addWidget(m_axLen,1,2); connect(w_ordWrapCB, SIGNAL(toggled(bool)), m_axLen, SLOT(setEnabled(bool))); o_wnSigCB=new QCheckBox(i18n("Appe&nd signature automatically"), generalB); generalL->addMultiCellWidget(o_wnSigCB,2,2,0,1); generalL->setColStretch(1,1); // === reply ============================================================= QGroupBox *replyB=new QGroupBox(i18n("Reply"), this); topL->addWidget(replyB); QGridLayout *replyL=new QGridLayout(replyB, 6,2, 8,5); replyL->addRowSpacing(0, fontMetrics().lineSpacing()-4); i_ntro=new QLineEdit(replyB); replyL->addMultiCellWidget(new QLabel(i_ntro,i18n("&Introduction Phrase:"), replyB),1,1,0,1); replyL->addMultiCellWidget(i_ntro, 2,2,0,1); replyL->addMultiCellWidget(new QLabel(i18n("Placeholders: %NAME=name, %EMAIL=email address,\n%DATE=date, %MSID=msgid"), replyB),3,3,0,1); r_ewrapCB=new QCheckBox(i18n("Rewrap quoted te&xt automatically"), replyB); replyL->addMultiCellWidget(r_ewrapCB, 5,5,0,1); a_uthSigCB=new QCheckBox(i18n("Include the a&uthors signature"), replyB); replyL->addMultiCellWidget(a_uthSigCB, 6,6,0,1); replyL->setColStretch(1,1); // === external editor ======================================================== QGroupBox *editorB=new QGroupBox(i18n("External Editor"), this); topL->addWidget(editorB); QGridLayout *editorL=new QGridLayout(editorB, 6,3, 8,5); editorL->addRowSpacing(0, fontMetrics().lineSpacing()-4); e_ditor=new QLineEdit(editorB); editorL->addWidget(new QLabel(e_ditor, i18n("Specify Edi&tor:"), editorB),1,0); editorL->addWidget(e_ditor,1,1); QPushButton *btn = new QPushButton(i18n("Choo&se..."),editorB); connect(btn, SIGNAL(clicked()), SLOT(slotChooseEditor())); editorL->addWidget(btn,1,2); editorL->addMultiCellWidget(new QLabel(i18n("%f will be replaced with the filename to edit."), editorB),2,2,0,2); e_xternCB=new QCheckBox(i18n("Start exte&rnal editor automatically"), editorB); editorL->addMultiCellWidget(e_xternCB, 3,3,0,2); editorL->setColStretch(1,1); topL->addStretch(1); //init w_ordWrapCB->setChecked(d->w_ordWrap); m_axLen->setEnabled(d->w_ordWrap); a_uthSigCB->setChecked(d->i_ncSig); e_xternCB->setChecked(d->u_seExtEditor); o_wnSigCB->setChecked(d->a_ppSig); r_ewrapCB->setChecked(d->r_ewrap); m_axLen->setValue(d->m_axLen); i_ntro->setText(d->i_ntro); e_ditor->setText(d->e_xternalEditor); } KNConfig::PostNewsComposerWidget::~PostNewsComposerWidget() { } void KNConfig::PostNewsComposerWidget::apply() { if(!d_irty) return; d_ata->w_ordWrap=w_ordWrapCB->isChecked(); d_ata->m_axLen=m_axLen->value(); d_ata->r_ewrap=r_ewrapCB->isChecked(); d_ata->a_ppSig=o_wnSigCB->isChecked(); d_ata->i_ntro=i_ntro->text(); d_ata->i_ncSig=a_uthSigCB->isChecked(); d_ata->e_xternalEditor=e_ditor->text(); d_ata->u_seExtEditor=e_xternCB->isChecked(); d_ata->save(); } void KNConfig::PostNewsComposerWidget::slotChooseEditor() { QString path=e_ditor->text().simplifyWhiteSpace(); if (path.right(3) == " %f") path.truncate(path.length()-3); path=KFileDialog::getOpenFileName(path, QString::null, this, i18n("Choose Editor")); if (!path.isEmpty()) e_ditor->setText(path+" %f"); } //=================================================================================================== KNConfig::PostNewsSpellingWidget::PostNewsSpellingWidget(QWidget *p, const char *n) : BaseWidget(p, n) { QVBoxLayout *topL=new QVBoxLayout(this, 5); c_onf = new KSpellConfig( this, "spell", 0, false ); topL->addWidget(c_onf); topL->addStretch(1); } KNConfig::PostNewsSpellingWidget::~PostNewsSpellingWidget() { } void KNConfig::PostNewsSpellingWidget::apply() { if(d_irty) c_onf->writeGlobalSettings(); } //============================================================================================================== KNConfig::PrivacyWidget::PrivacyWidget(Privacy *pr, QWidget *p, const char *n) : BaseWidget(p,n), d_ata(pr) { // QVBoxLayout *topL = new QVBoxLayout(this, 2); QGridLayout *topL=new QGridLayout(this, 3,3, 8,5); // don't use a groupbox as long as we have nothing to group in here (CG) // === groups =========================================================== // QGroupBox *groupsB=new QGroupBox(this); // QGridLayout *groupsL=new QGridLayout(groupsB, 2,3, 8,5); // groupsL->addRowSpacing(0, fontMetrics().lineSpacing()-4); pgp_version = new QComboBox(this); QLabel *l1 = new QLabel(pgp_version,i18n("&PGP version"), this); topL->addWidget(l1,0,0); topL->addMultiCellWidget(pgp_version,0,0,1,2); connect(pgp_version, SIGNAL(activated(int)), SLOT(slotDefaultProg(int))); pgp_path = new QLineEdit(this); l1 =new QLabel(pgp_path, i18n("Crypt progra&m:"), this); topL->addWidget(l1,1,0); topL->addWidget(pgp_path,1,1); QPushButton *choosePgp = new QPushButton(i18n("Choo&se..."),this); topL->addWidget(choosePgp,1,2); connect(choosePgp, SIGNAL(clicked()), SLOT(slotChoosePgp())); //l1 = new QLabel(i18n("alternate keyring:"), groupsB); //groupsL->addWidget(l1,3,0); //keyring = new QLineEdit(groupsB); //groupsL->addWidget(keyring,3,1); //l1 = new QLabel(i18n("keyserver:"), groupsB); //groupsL->addWidget(l1,4,0); //keyserv = new QLineEdit(groupsB); //groupsL->addWidget(keyserv,4,1); //l1 = new QLabel(i18n("PGP method"), groupsB); //groupsL->addWidget(l1,5,0); //enc_style = new QComboBox(groupsB); //groupsL->addWidget(enc_style,5,1); //keeppasswd = new QCheckBox("keep passphrase in memory",groupsB); //groupsL->addMultiCellWidget(keeppasswd, 6,6,0,1); topL->setColStretch(1,1); topL->setRowStretch(2,1); // topL->addWidget(groupsB); // topL->addStretch(1); // === init =========================================================== pgp_version->insertStringList(d_ata->v_ersions); pgp_version->setCurrentItem(d_ata->v_ersion); pgp_path->setText(d_ata->p_rogpath); //keyring->setText(d_ata->k_eyring); //keyserv->setText(d_ata->k_eyserv); //enc_style->insertStringList(d_ata->e_ncodings); //enc_style->setCurrentItem(d_ata->e_ncoding); //keeppasswd->setChecked(d_ata->k_eeppasswd); //kdDebug(5003) << k_funcinfo << endl; } void KNConfig::PrivacyWidget::slotChoosePgp() { QString path = pgp_path->text().simplifyWhiteSpace(); path = KFileDialog::getOpenFileName(path, QString::null, this, i18n("Choose PGP binary")); if (!path.isEmpty()) pgp_path->setText(path); } void KNConfig::PrivacyWidget::slotDefaultProg(int version) { pgp_path->setText(d_ata->defaultProg(version)); } KNConfig::PrivacyWidget::~PrivacyWidget() { } void KNConfig::PrivacyWidget::apply() { if(!d_irty) return; d_ata->v_ersion = pgp_version->currentItem(); //d_ata->e_ncoding = enc_style->currentItem(); //d_ata->k_eeppasswd = keeppasswd->isChecked(); //d_ata->k_eyring = keyring->text(); d_ata->p_rogpath = pgp_path->text(); d_ata->save(); } //============================================================================================================== KNConfig::CleanupWidget::CleanupWidget(Cleanup *d, QWidget *p, const char *n) : BaseWidget(p, n), d_ata(d) { QVBoxLayout *topL=new QVBoxLayout(this, 5); // === groups =========================================================== QGroupBox *groupsB=new QGroupBox(i18n("Groups"), this); topL->addWidget(groupsB); QGridLayout *groupsL=new QGridLayout(groupsB, 6,2, 8,5); groupsL->addRowSpacing(0, fontMetrics().lineSpacing()-4); g_roupCB=new QCheckBox(i18n("&Remove old articles from newsgroups"), groupsB); connect(g_roupCB, SIGNAL(toggled(bool)), this, SLOT(slotGroupCBtoggled(bool))); groupsL->addMultiCellWidget(g_roupCB,1,1,0,1); g_roupDays=new KIntSpinBox(0, 999, 1, 0, 10, groupsB); g_roupDays->setSuffix(i18n(" days")); g_roupDaysL=new QLabel(g_roupDays,i18n("&Purge groups every"), groupsB); groupsL->addWidget(g_roupDaysL,2,0); groupsL->addWidget(g_roupDays,2,1,Qt::AlignRight); r_eadDays=new KIntSpinBox(0, 999, 1, 0, 10, groupsB); r_eadDays->setSuffix(i18n(" days")); r_eadDaysL=new QLabel(r_eadDays, i18n("&Keep read articles"), groupsB); groupsL->addWidget(r_eadDaysL,3,0); groupsL->addWidget(r_eadDays,3,1,Qt::AlignRight); u_nreadDays=new KIntSpinBox(0, 999, 1, 0, 10, groupsB); u_nreadDays->setSuffix(i18n(" days")); u_nreadDaysL=new QLabel(u_nreadDays, i18n("Keep u&nread articles"), groupsB); groupsL->addWidget(u_nreadDaysL,4,0); groupsL->addWidget(u_nreadDays,4,1,Qt::AlignRight); t_hrCB=new QCheckBox(i18n("Preser&ve threads"), groupsB); groupsL->addWidget(t_hrCB,5,0); groupsL->setColStretch(1,1); // === folders ========================================================= QGroupBox *foldersB=new QGroupBox(i18n("Folders"), this); topL->addWidget(foldersB); QGridLayout *foldersL=new QGridLayout(foldersB, 3,2, 8,5); foldersL->addRowSpacing(0, fontMetrics().lineSpacing()-4); f_olderCB=new QCheckBox(i18n("Co&mpact folders"), foldersB); connect(f_olderCB, SIGNAL(toggled(bool)), this, SLOT(slotFolderCBtoggled(bool))); foldersL->addMultiCellWidget(f_olderCB,1,1,0,1); f_olderDays=new KIntSpinBox(0, 999, 1, 0, 10, foldersB); f_olderDays->setSuffix(i18n(" days")); f_olderDaysL=new QLabel(f_olderDays,i18n("P&urge folders every"), foldersB); foldersL->addWidget(f_olderDaysL,2,0); foldersL->addWidget(f_olderDays,2,1,Qt::AlignRight); foldersL->setColStretch(1,1); topL->addStretch(1); //init f_olderCB->setChecked(d->d_oCompact); slotFolderCBtoggled(d->d_oCompact); g_roupCB->setChecked(d->d_oExpire); slotGroupCBtoggled(d->d_oExpire); t_hrCB->setChecked(d->p_reserveThr); f_olderDays->setValue(d->c_ompactInterval); g_roupDays->setValue(d->e_xpireInterval); r_eadDays->setValue(d->r_eadMaxAge); u_nreadDays->setValue(d->u_nreadMaxAge); } KNConfig::CleanupWidget::~CleanupWidget() { } void KNConfig::CleanupWidget::apply() { if(!d_irty) return; d_ata->d_oExpire=g_roupCB->isChecked(); d_ata->e_xpireInterval=g_roupDays->value(); d_ata->u_nreadMaxAge=u_nreadDays->value(); d_ata->r_eadMaxAge=r_eadDays->value(); d_ata->p_reserveThr=t_hrCB->isChecked(); d_ata->d_oCompact=f_olderCB->isChecked(); d_ata->c_ompactInterval=f_olderDays->value(); d_ata->save(); } void KNConfig::CleanupWidget::slotGroupCBtoggled(bool b) { g_roupDaysL->setEnabled(b); g_roupDays->setEnabled(b); r_eadDaysL->setEnabled(b); r_eadDays->setEnabled(b); u_nreadDaysL->setEnabled(b); u_nreadDays->setEnabled(b); t_hrCB->setEnabled(b); } void KNConfig::CleanupWidget::slotFolderCBtoggled(bool b) { f_olderDaysL->setEnabled(b); f_olderDays->setEnabled(b); } //------------------------ #include "knconfig.moc" diff --git a/knode/knfolder.cpp b/knode/knfolder.cpp index cfbc2d2a00..e5548490b7 100644 --- a/knode/knfolder.cpp +++ b/knode/knfolder.cpp @@ -1,481 +1,508 @@ /* knfolder.cpp KNode, the KDE newsreader Copyright (c) 1999-2000 the KNode authors. See file AUTHORS for details This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, US */ #include #include #include #include #include #include "knaccountmanager.h" #include "knarticlemanager.h" #include "knnntpaccount.h" #include "knstringsplitter.h" #include "kncollectionviewitem.h" #include "knhdrviewitem.h" #include "utilities.h" #include "knglobals.h" #include "knarticlefactory.h" #include "knfolder.h" #include "knarticlewidget.h" #include "knarticlewindow.h" KNFolder::KNFolder(int id, const QString &name, KNCollection *parent) : KNArticleCollection(parent) , i_d(id), i_ndexDirty(false) { n_ame=name; QString fname=path()+QString("%1_%2.").arg(n_ame).arg(i_d); m_boxFile.setName(fname+"mbox"); i_ndexFile.setName(fname+"idx"); } KNFolder::KNFolder(int id, const QString &name, const QString &prefix, KNCollection *parent) : KNArticleCollection(parent) , i_d(id), i_ndexDirty(false) { n_ame=name; QString fname=path()+QString("%1_%2.").arg(prefix).arg(i_d); m_boxFile.setName(fname+"mbox"); i_ndexFile.setName(fname+"idx"); } KNFolder::~KNFolder() { if(i_ndexDirty) syncIndex(); closeFiles(); } void KNFolder::updateListItem() { if(l_istItem) l_istItem->setNumber(1,c_ount); } QString KNFolder::path() { QString dir(KGlobal::dirs()->saveLocation("appdata","folders/")); /*if (dir==QString::null) displayInternalFileError();*/ return dir; } bool KNFolder::readInfo(const QString &) { #warning IMPLEMENT ME return true; } void KNFolder::saveInfo() { #warning IMPLEMENT ME /*QString dir(path()); if (dir!=QString::null) { int pId=-1; //if(p_arent) pId=p_arent->id(); KSimpleConfig info(dir+QString("folder%1.info").arg(i_d)); info.writeEntry("foldername", n_ame); info.writeEntry("id", i_d); info.writeEntry("parentId", pId); info.writeEntry("count", c_ount); }*/ } KNLocalArticle* KNFolder::byId(int id) { int idx=findId(id); if(idx!=-1) return ( static_cast(list[idx]) ); else return 0; } bool KNFolder::loadHdrs() { if(c_ount==0 || len>0) { kdDebug(5003) << "KNFolder::loadHdrs() : already loaded" << endl; return true; } if(!i_ndexFile.open(IO_ReadOnly)) { kdError(5003) << "KNFolder::loadHdrs() : cannot open index-file!" << endl; closeFiles(); return false; } if(!m_boxFile.open(IO_ReadOnly)) { kdError(5003) << "KNFolder::loadHdrs() : cannot open mbox-file!" << endl; closeFiles(); return false; } if(!resize(c_ount)) { closeFiles(); return false; } QCString tmp; KNStringSplitter split; KNLocalArticle *art; DynData dynamic; int pos1=0, pos2=0, cnt=0, byteCount; while(!i_ndexFile.atEnd()) { //read index-data byteCount=i_ndexFile.readBlock((char*)(&dynamic), sizeof(DynData)); if(byteCount!=sizeof(DynData)) if(i_ndexFile.status() == IO_Ok) { kdWarning(5003) << "KNFolder::loadHeaders() : found broken entry in index-file: Ignored!" << endl; continue; } else { kdError(5003) << "KNFolder::loadHeaders() : corrupted index-file, IO-error!" << endl; closeFiles(); clearList(); return false; } art=new KNLocalArticle(this); //set index-data art->setId(dynamic.id); art->date()->setUnixTime(dynamic.ti); art->setStartOffset(dynamic.so); art->setEndOffset(dynamic.eo); art->setServerId(dynamic.sId); art->setDoMail(dynamic.flags[0]); art->setMailed(dynamic.flags[1]); art->setDoPost(dynamic.flags[2]); art->setPosted(dynamic.flags[3]); art->setCanceled(dynamic.flags[4]); art->setEditDisabled(dynamic.flags[5]); //read overview if(!m_boxFile.at(art->startOffset())) { kdError(5003) << "KNFolder::loadHdrs() : cannot set mbox file-pointer!" << endl; closeFiles(); clearList(); return false; } tmp=m_boxFile.readLine(); //KNFile::readLine() if(tmp.isEmpty()) { if(m_boxFile.status() == IO_Ok) { kdWarning(5003) << "found broken entry in mbox-file: Ignored!" << endl; delete art; continue; } else { kdError(5003) << "KNFolder::loadHdrs() : corrupted mbox-file, IO-error!"<< endl; closeFiles(); clearList(); return false; } } //set overview + bool end=false; pos1=tmp.find(' ')+1; pos2=tmp.find('\t', pos1); + if (pos2 == -1) { + pos2=tmp.length(); + end=true; + } art->subject()->from7BitString(tmp.mid(pos1, pos2-pos1), art->defaultCharset(),false); - pos1=pos2+1; - pos2=tmp.find('\t', pos1); - art->newsgroups()->from7BitString(tmp.mid(pos1, pos2-pos1), art->defaultCharset(),false); - pos1=pos2+1; - pos2=tmp.length(); - art->to()->from7BitString(tmp.mid(pos1,pos2-pos1), art->defaultCharset(),false); + + if (!end) { + pos1=pos2+1; + pos2=tmp.find('\t', pos1); + if (pos2 == -1) { + pos2=tmp.length(); + end=true; + } + art->newsgroups()->from7BitString(tmp.mid(pos1, pos2-pos1), art->defaultCharset(),false); + } + + if (!end) { + pos1=pos2+1; + pos2=tmp.find('\t', pos1); + if (pos2 == -1) { + pos2=tmp.length(); + end=true; + } + art->to()->from7BitString(tmp.mid(pos1,pos2-pos1), art->defaultCharset(),false); + } + + if (!end) { + pos1=pos2+1; + pos2=tmp.length(); + art->lines()->from7BitString(tmp.mid(pos1,pos2-pos1), art->defaultCharset(),false); + } if(!append(art)) { kdError(5003) << "KNFolder::loadHdrs() : cannot append article!"<< endl; delete art; clearList(); closeFiles(); return false; } cnt++; } closeFiles(); setLastID(); c_ount=cnt; updateListItem(); return true; } bool KNFolder::loadArticle(KNLocalArticle *a) { if(a->hasContent()) return true; closeFiles(); if(!m_boxFile.open(IO_ReadOnly)) { kdError(5003) << "KNFolder::loadArticle(KNLocalArticle *a) : cannot open mbox file: " << m_boxFile.name() << endl; return false; } //set file-pointer if(!m_boxFile.at(a->startOffset())) { kdError(5003) << "KNFolder::loadArticle(KNLocalArticle *a) : cannot set mbox file-pointer!" << endl; closeFiles(); return false; } //read content m_boxFile.readLine(); //skip X-KNode-Overview unsigned int size=a->endOffset()-m_boxFile.at(); QCString buff(size+10); int readBytes=m_boxFile.readBlock(buff.data(), size); closeFiles(); if(readBytes < (int)(size) && m_boxFile.status() != IO_Ok) { //cannot read file kdError(5003) << "KNFolder::loadArticle(KNLocalArticle *a) : corrupted mbox file, IO-error!" << endl; return false; } //set content buff.at(readBytes)='\0'; //terminate string a->setContent(buff); a->parse(); return true; } bool KNFolder::saveArticles(KNLocalArticle::List *l) { if(!loadHdrs()) return false; if(!m_boxFile.open(IO_WriteOnly | IO_Append)) { kdError(5003) << "KNFolder::loadHdrs() : cannot open mbox-file!" << endl; closeFiles(); return false; } int idx=0, addCnt=0; bool ret=true; QTextStream ts(&m_boxFile); ts.setEncoding(QTextStream::Latin1); DynData dynamic; for(KNLocalArticle *a=l->first(); a; a=l->next()) { if(a->id()==-1 || a->collection()!=this) { if(a->id()!=-1) { KNFolder *oldFolder=static_cast(a->collection()); if(!a->hasContent()) if(!oldFolder->loadArticle(a)) { ret=false; continue; } KNLocalArticle::List l; l.append(a); oldFolder->removeArticles(&l, false); } if(!append(a)) { kdError(5003) << "KNFolder::saveArticle(KNLocalArticle::List *l) : cannot append article!" << endl; ret=false; continue; a->setCollection(0); } else { a->setCollection(this); addCnt++; } } idx=findId(a->id()); if(idx!=-1 && at(idx)==a) { //MBox ts << "From aaa@aaa Mon Jan 01 00:00:00 1997\n"; a->setStartOffset(m_boxFile.at()); //save offset //write overview information ts << "X-KNode-Overview: "; ts << a->subject()->as7BitString(false) << '\t'; KNHeaders::Base* h; if( (h=a->newsgroups(false))!=0 ) ts << h->as7BitString(false); ts << '\t'; if( (h=a->to(false))!=0 ) ts << h->as7BitString(false); - ts << '\n'; + ts << '\t'; + + ts << a->lines()->as7BitString(false) << '\n'; //write article a->toStream(ts); ts << '\n'; a->setEndOffset(m_boxFile.at()); //save offset //update KNArticleWidget::articleChanged(a); i_ndexDirty=true; } else { kdError(5003) << "KNFolder::saveArticle() : article not in folder!" << endl; ret=false; } } closeFiles(); if(addCnt>0) { c_ount=len; updateListItem(); knGlobals.artManager->updateViewForCollection(this); } return ret; } void KNFolder::removeArticles(KNLocalArticle::List *l, bool del) { if(l->isEmpty()) return; int idx=0, delCnt=0, *positions; positions=new int[l->count()]; KNLocalArticle *a=0; for(a=l->first(); a; a=l->next()) { idx=l->at(); if(a->isLocked()) positions[idx]=-1; else positions[idx]=findId(a->id()); } for(idx=0; idx < (int)(l->count()); idx++) { if(positions[idx]==-1) continue; a=at(positions[idx]); list[(positions[idx])]=0; delCnt++; //update knGlobals.artFactory->deleteComposerForArticle(a); KNArticleWindow::closeAllWindowsForArticle(a); KNArticleWidget::articleRemoved(a); delete a->listItem(); //delete article if(del) delete a; else a->setId(-1); } if(delCnt>0) { compactList(); c_ount-=delCnt; updateListItem(); i_ndexDirty=true; } delete positions; } void KNFolder::deleteAll() { if(l_ockedArticles>0) return; KNLocalArticle *a; for(int idx=0; idxdeleteComposerForArticle(a); KNArticleWindow::closeAllWindowsForArticle(a); KNArticleWidget::articleRemoved(a); } clearList(); c_ount=0; syncIndex(true); saveInfo(); updateListItem(); } void KNFolder::syncIndex(bool force) { if(!i_ndexDirty && !force) return; if(!i_ndexFile.open(IO_WriteOnly)) { kdError(5003) << "KNFolder::syncIndex(bool force) : cannot open index-file!" << endl; closeFiles(); return; } KNLocalArticle *a; DynData d; for(int idx=0; idxid(); so=a->startOffset(); eo=a->endOffset(); sId=a->serverId(); ti=a->date()->unixTime(); flags[0]=a->doMail(); flags[1]=a->mailed(); flags[2]=a->doPost(); flags[3]=a->posted(); flags[4]=a->canceled(); flags[5]=a->editDisabled(); } diff --git a/knode/knhdrviewitem.cpp b/knode/knhdrviewitem.cpp index 01a5ad80bc..af8960877f 100644 --- a/knode/knhdrviewitem.cpp +++ b/knode/knhdrviewitem.cpp @@ -1,120 +1,124 @@ /* knhdrviewitem.cpp KNode, the KDE newsreader Copyright (c) 1999-2000 the KNode authors. See file AUTHORS for details This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, US */ #include #include #include "knglobals.h" #include "knconfigmanager.h" #include "knhdrviewitem.h" #include "knmime.h" KNHdrViewItem::KNHdrViewItem(KNListView *ref, KNArticle *a) : KNLVItemBase(ref), art(a), subjectCS(QFont::ISO_8859_1), nameCS(QFont::ISO_8859_1) { } KNHdrViewItem::KNHdrViewItem(KNLVItemBase *ref, KNArticle *a) : KNLVItemBase(ref), art(a) { } KNHdrViewItem::~KNHdrViewItem() { if(art) art->setListItem(0); } QString KNHdrViewItem::key(int col, bool) const { - if(col==3) { + if ((col==2)||(col==3)) { // score, lines + QString tmpString; + return tmpString.sprintf("%08d",text(col).toInt()); + } + if (col==4) { // date QString tmpString; return tmpString.sprintf("%08d",(uint)art->date()->unixTime()); - } else - return text(col); + } + return text(col); } QCache KNHdrViewItem::f_ontCache; void KNHdrViewItem::clearFontCache() { f_ontCache.setAutoDelete(true); f_ontCache.clear(); } bool KNHdrViewItem::greyOut() { if(art->type()==KNMimeBase::ATremote) return ( !((KNRemoteArticle*)art)->hasUnreadFollowUps() && ((KNRemoteArticle*)art)->isRead() ); else return false; } bool KNHdrViewItem::firstColBold() { if(art->type()==KNMimeBase::ATremote) return ( static_cast(art)->isNew() ); else return false; } QColor KNHdrViewItem::normalColor() { return knGlobals.cfgManager->appearance()->unreadArticleColor(); } QColor KNHdrViewItem::greyColor() { return knGlobals.cfgManager->appearance()->readArticleColor(); } const QFont& KNHdrViewItem::fontForColumn(int col, const QFont &font) { if (col>1) return font; QFont *f=0; QFont::CharSet cs; if (col==0) cs = subjectCS; else cs = nameCS; // check if we already have a suitable font in the cache f=f_ontCache.find(QString::number((int)(cs))); if (f) return (*f); // new charset... f = new QFont(knGlobals.cfgManager->appearance()->articleListFont()); KGlobal::charsets()->setQFont(*f, cs); f_ontCache.setAutoDelete(true); f_ontCache.insert(QString::number((int)(cs)),f); return (*f); } diff --git a/knode/knlistview.cpp b/knode/knlistview.cpp index 2b76370149..7d0ad78b1e 100644 --- a/knode/knlistview.cpp +++ b/knode/knlistview.cpp @@ -1,309 +1,314 @@ /* knlistview.cpp KNode, the KDE newsreader Copyright (c) 1999-2000 the KNode authors. See file AUTHORS for details This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, US */ #include #include #include #include #include #include #include "knglobals.h" #include "knconfigmanager.h" #include "utilities.h" #include "knlistview.h" #include "knmime.h" #include "knhdrviewitem.h" KNLVItemBase::KNLVItemBase(KNLVItemBase *item) : QListViewItem(item), active(false) { } KNLVItemBase::KNLVItemBase(KNListView *view) : QListViewItem(view), active(false) { } KNLVItemBase::~KNLVItemBase() { if(active) { QListView *lv=listView(); // no need to check necessary, a KNLVItemBase objects can only be added to KNListViews if(lv) (static_cast(lv))->activeRemoved(); } } void KNLVItemBase::paintCell(QPainter *p, const QColorGroup &cg, int column, int width, int alignment) { int xText=0, xPM=3, yPM=0; QColor base; KNConfig::Appearance *app=knGlobals.cfgManager->appearance(); p->setFont(fontForColumn(column, p->font())); QPen pen=p->pen(); if (isSelected()||active) { pen.setColor(cg.highlightedText()); if (active) base=app->activeItemColor(); else base=app->selectedItemColor(); } else { if (this->greyOut()) pen.setColor(greyColor()); else pen.setColor(normalColor()); base=cg.base(); } p->setPen(pen); p->fillRect(0,0,width, height(), QBrush(base)); if(column==0) { if(this->firstColBold()) { QFont font=p->font(); font.setBold(true); p->setFont(font); } const QPixmap *pm; for(int i=0; i<4; i++) { pm=pixmap(i); if(pm) if(!pm->isNull()) { yPM = (height() - pm->height())/2; p->drawPixmap(xPM, yPM, *pm); xPM+=pm->width()+3; } } xText=xPM; } if (width-xText-5 > 0) { QString t = shortString(text(column),column,width-xText-5,p->fontMetrics()); p->drawText(xText, 0, width-xText-5, height(), alignment | AlignVCenter, t); } } int KNLVItemBase::width(const QFontMetrics &fm, const QListView *, int column) { int ret = fm.boundingRect( text(column) ).width(); if(column==0) { int i=0; const QPixmap *pm=pixmap(i); while(pm) { ret+=pixmap(i)->width()+3; i++; } } return ret; } void KNLVItemBase::paintFocus(QPainter *p, const QColorGroup & cg, const QRect & r) { p->setPen(QPen(cg.foreground(),1, DotLine)); p->drawRect(r.x(), r.y(), r.width()-3, r.height()); } void KNLVItemBase::sortChildItems(int column, bool b) { QListViewItem::sortChildItems(column, b); } void KNLVItemBase::expandChildren() { QListViewItemIterator it(firstChild()); for( ; it.current(); ++it) { if(it.current()->depth()==depth()) break; it.current()->setOpen(true); } } QColor KNLVItemBase::normalColor() { return knGlobals.cfgManager->appearance()->textColor(); } QColor KNLVItemBase::greyColor() { return knGlobals.cfgManager->appearance()->textColor(); } QString KNLVItemBase::shortString(QString text, int, int width, QFontMetrics fm) { QString t(text); int ew = fm.width("..."); if (fm.width(t) > width) { for (int i=t.length();i>0;i--) if (fm.width(t)+ew > width) t.truncate(i); t += "..."; } return t; } //============================================================================== KNListView::KNListView(QWidget *parent, const char *name) : QListView(parent,name), sAsc(true), sCol(-1), activeItem(0) { connect(header(), SIGNAL(sectionClicked(int)), - this, SLOT(slotSortList(int))); + this, SLOT(slotSectionClicked(int))); disconnect(header(), SIGNAL(sizeChange(int,int,int))); connect(header(), SIGNAL(sizeChange(int,int,int)), this, SLOT(slotSizeChanged(int,int,int))); header()->setMovingEnabled(true); setFrameStyle(NoFrame); setSelectionMode(QListView::Extended); } KNListView::~KNListView() { } void KNListView::setActive(QListViewItem *i, bool activate) { KNLVItemBase *item = static_cast(i); if (!item || (item->isActive() == activate)) return; if (activeItem) { activeItem->setActive(false); repaintItem(activeItem); activeItem=0; } item->setActive(activate); if (activate) { clearSelection(); setSelected(item,true); activeItem = item; emit(itemSelected(item)); } else repaintItem(item); } void KNListView::clear() { activeItem=0; QListView::clear(); } -void KNListView::slotSortList(int section) +void KNListView::slotSectionClicked(int section) { int col = header()->mapToIndex(section); + slotSortList(col); +} + +void KNListView::slotSortList(int col) +{ if(col==sCol) sAsc=!sAsc; else { emit sortingChanged(col); sCol=col; } - setSorting(sCol, sAsc); + setSorting(col, sAsc); if(currentItem()!=0) ensureItemVisible(currentItem()); } void KNListView::slotSizeChanged(int section, int, int newSize) { viewport()->repaint( header()->sectionPos(section), 0, newSize, visibleHeight(), false); } void KNListView::contentsMousePressEvent(QMouseEvent *e) { if (!e) return; bool selectMode=(( e->state() & ShiftButton ) || ( e->state() & ControlButton )); QListView::contentsMousePressEvent(e); QListViewItem *i=currentItem(); if (i && !selectMode && i->isSelected()) setActive(i, true); } void KNListView::keyPressEvent(QKeyEvent *e) { if (!e) return; QListViewItem *i=currentItem(); switch(e->key()) { case Key_Space: case Key_Backspace: case Key_Delete: e->ignore(); // don't eat them break; case Key_Enter: case Key_Return: setActive(i, true); ensureItemVisible(i); break; default: QListView::keyPressEvent (e); } } void KNListView::focusInEvent(QFocusEvent *e) { QListView::focusInEvent(e); emit focusChanged(e); } void KNListView::focusOutEvent(QFocusEvent *e) { QListView::focusOutEvent(e); emit focusChanged(e); } //-------------------------------- #include "knlistview.moc" diff --git a/knode/knlistview.h b/knode/knlistview.h index 3555f78d3c..6aed04b1d6 100644 --- a/knode/knlistview.h +++ b/knode/knlistview.h @@ -1,99 +1,100 @@ /* knlistview.h KNode, the KDE newsreader Copyright (c) 1999-2000 the KNode authors. See file AUTHORS for details This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, US */ #ifndef KNLISTVIEW_H #define KNLISTVIEW_H #include #include #include class KNListView; class KNLVItemBase : public QListViewItem { public: KNLVItemBase(KNListView *view); // restricted to KNListView to prevent that the KNLVItemBase(KNLVItemBase *item); // static_cast in ~KNLVItemBase fails. ~KNLVItemBase(); void setActive(bool b) { active = b; }; bool isActive() { return active; } void paintCell(QPainter *p, const QColorGroup &cg, int column, int width, int alignment); int width(const QFontMetrics &fm, const QListView *lv, int column); void paintFocus(QPainter *, const QColorGroup & cg, const QRect & r); void sortChildItems(int column, bool a); void expandChildren(); protected: virtual bool greyOut() { return false; } virtual bool firstColBold() { return false; } virtual QColor normalColor(); virtual QColor greyColor(); virtual QString shortString(QString text, int col, int width, QFontMetrics fm); virtual const QFont& fontForColumn(int, const QFont &font) { return font; } private: bool active; }; class KNListView : public QListView { Q_OBJECT friend class KNLVItemBase; public: KNListView(QWidget *parent, const char *name=0); ~KNListView(); int sortColumn() { return sCol; } bool ascending() { return sAsc; } void setColAsc(int c, bool a) { sCol=c; sAsc=a; } void setActive(QListViewItem *item, bool activate); void clear(); public slots: + void slotSectionClicked(int section); void slotSortList(int col); void slotSizeChanged(int,int,int); protected: void activeRemoved() { activeItem = 0; } void contentsMousePressEvent(QMouseEvent *e); void keyPressEvent(QKeyEvent *e); void focusInEvent(QFocusEvent *e); void focusOutEvent(QFocusEvent *e); bool sAsc; int sCol; signals: void itemSelected(QListViewItem*); void sortingChanged(int); void focusChanged(QFocusEvent*); private: KNLVItemBase *activeItem; }; #endif diff --git a/knode/knmime.cpp b/knode/knmime.cpp index 28b6c8d206..1780b97589 100644 --- a/knode/knmime.cpp +++ b/knode/knmime.cpp @@ -1,1893 +1,1900 @@ /* knmime.cpp KNode, the KDE newsreader Copyright (c) 1999-2000 the KNode authors. See file AUTHORS for details This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, US */ #include #include #include #include #include #include #include #include #include #include #include #include #include "knmime.h" #include "knhdrviewitem.h" #include "kngroup.h" #include "knglobals.h" #include "knconfigmanager.h" #include "utilities.h" QString KNMimeBase::decodeRFC2047String(const QCString &src, QFont::CharSet &cs, bool force) { QCString result, str; QCString charset; DwString dwsrc, dwdest; char *pos, *dest, *beg, *end, *mid; char encoding, ch; bool valid; const int maxLen=400; int i; if(src.find("=?") < 0) result = src.copy(); else { result.truncate(src.length()); for (pos=src.data(), dest=result.data(); *pos; pos++) { if (pos[0]!='=' || pos[1]!='?') { *dest++ = *pos; continue; } beg = pos+2; end = beg; valid = TRUE; // parse charset name charset=""; for (i=2,pos+=2; i=maxLen) valid = FALSE; else { // get encoding and check delimiting question marks encoding = toupper(pos[1]); if (pos[2]!='?' || (encoding!='Q' && encoding!='B')) valid = FALSE; pos+=3; i+=3; } if (valid) { mid = pos; // search for end of encoded part while (i=maxLen || !*pos) valid = FALSE; } if (valid) { ch = *pos; *pos = '\0'; str = QCString(mid, (int)(mid - pos - 1)); if (encoding == 'Q') { // decode quoted printable text for (i=str.length()-1; i>=0; i--) if (str[i]=='_') str[i]=' '; dwsrc=str.data(); DwDecodeQuotedPrintable(dwsrc, dwdest); str = dwdest.c_str(); } else { // decode base64 text dwsrc=str.data(); DwDecodeBase64(dwsrc, dwdest); str = dwdest.c_str(); } *pos = ch; for (i=0; str[i]; i++) *dest++ = str[i]; pos = end -1; } else { //result += "=?"; //pos = beg -1; // because pos gets increased shortly afterwards pos = beg - 2; *dest++ = *pos++; *dest++ = *pos; } } *dest = '\0'; } //convert to unicode QTextCodec *codec=0; bool ok=true; if (force || charset.isEmpty()) codec=KGlobal::charsets()->codecForName(KGlobal::charsets()->name(cs),ok); else { codec=KGlobal::charsets()->codecForName(charset,ok); if(!ok) { //no suitable codec found => use default charset codec=KGlobal::charsets()->codecForName(KGlobal::charsets()->name(cs),ok); } else cs=KGlobal::charsets()->charsetForEncoding(charset); } return codec->toUnicode(result.data(), result.length()); } QCString KNMimeBase::encodeRFC2047String(const QString &src, QFont::CharSet cs) { QCString encoded8Bit, result, chset; unsigned int start=0,end=0; bool nonAscii=false, ok=true; QTextCodec *codec=0; KNConfig::PostNewsTechnical *pnt=knGlobals.cfgManager->postNewsTechnical(); codec=KGlobal::charsets()->codecForName(KGlobal::charsets()->name(cs),ok); if(!ok) { //no codec available => try local8Bit and hope the best ;-) chset=KGlobal::locale()->charset().latin1(); codec=KGlobal::charsets()->codecForName(chset,ok); } else { chset=pnt->findComposerCharset(cs); // find a clean name for the charset if (chset.isEmpty()) chset=KGlobal::charsets()->name(cs).latin1(); // this name has a invalid format! } encoded8Bit=codec->fromUnicode(src); if(pnt->allow8BitHeaders()) return encoded8Bit; for (unsigned int i=0; i='a')&&(c<='z'))|| // paranoid mode, we encode *all* special characters to avoid problems ((c>='A')&&(c<='Z'))|| // with "From" & "To" headers ((c>='0')&&(c<='9'))) result+=c; else { result += "="; // "stolen" from KMail ;-) hexcode = ((c & 0xF0) >> 4) + 48; if (hexcode >= 58) hexcode += 7; result += hexcode; hexcode = (c & 0x0F) + 48; if (hexcode >= 58) hexcode += 7; result += hexcode; } } result +="?="; result += encoded8Bit.right(encoded8Bit.length()-end); } else result = encoded8Bit; return result; } QCString KNMimeBase::uniqueString() { static char chars[] = "0123456789abcdefghijklmnopqrstuvxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; time_t now; QCString ret; char p[11]; int pos, ran; unsigned int timeval; p[10]='\0'; now=time(0); ran=1+(int) (1000.0*rand()/(RAND_MAX+1.0)); timeval=(now/ran)+getpid(); for(int i=0; i<10; i++){ pos=(int) (61.0*rand()/(RAND_MAX+1.0)); //kdDebug(5003) << pos << endl; p[i]=chars[pos]; } ret.sprintf("%d.%s", timeval, p); return ret; } QCString KNMimeBase::multiPartBoundary() { QCString ret; ret="nextPart"+uniqueString(); return ret; } QCString KNMimeBase::CRLFtoLF(const QCString &s) { QCString ret=s.copy(); ret.replace(QRegExp("\\r\\n"), "\n"); return ret; } QCString KNMimeBase::CRLFtoLF(const char *s) { QCString ret=s; ret.replace(QRegExp("\\r\\n"), "\n"); return ret; } QCString KNMimeBase::LFtoCRLF(const QCString &s) { QCString ret=s.copy(); ret.replace(QRegExp("\\n"), "\r\n"); return ret; } void KNMimeBase::stripCRLF(char *str) { int pos=strlen(str)-1; while(str[pos]!='\n' && pos>0) pos--; if(pos>0) { str[pos--]='\0'; if(str[pos]=='\r') str[pos]='\0'; } } void KNMimeBase::removeQuots(QCString &str) { int pos1=0, pos2=0; if((pos1=str.find('"'))!=-1) if((pos2=str.findRev('"'))!=-1) if(pos1 skip it; } if(pos1>-1) { pos1+=blen; if(s_rc[pos1]=='-' && s_rc[pos1+1]=='-') // the only valid boundary is the end-boundary - this message is *really* broken pos1=-1; //we give up else if( (pos1-blen)>1 ) //preamble present p_reamble=s_rc.left(pos1-blen); } while(pos1>-1 && pos2>-1) { //skip the rest of the line for the first boundary - the message-part starts here if( (pos1=s_rc.find('\n', pos1))>-1 ) { //now search the next linebreak //now find the next valid boundary pos2=++pos1; //pos1 and pos2 point now to the beginning of the next line after the boundary while(1) { if( (pos2=s_rc.find(b, pos2))==-1 || s_rc[pos2-1]=='\n' ) //valid boundary or no more boundaries found break; pos2+=blen; //boundary is invalid => skip it; } if(pos2==-1) { // no more boundaries found part=s_rc.mid(pos1, s_rc.length()-pos1); //take the rest of the string p_arts.append(part); pos1=-1; pos2=-1; //break; } else { part=s_rc.mid(pos1, pos2-pos1); p_arts.append(part); pos2+=blen; //pos2 points now to the first charakter after the boundary if(s_rc[pos2]=='-' && s_rc[pos2+1]=='-') { //end-boundary pos1=pos2+2; //pos1 points now to the character directly after the end-boundary if( (pos1=s_rc.find('\n', pos1))>-1 ) //skipt the rest of this line e_pilouge=s_rc.mid(++pos1, s_rc.length()-pos1); //everything after the end-boundary is considered as the epilouge pos1=-1; pos2=-1; //break } else { pos1=pos2; //the search continues ... } } } } return (!p_arts.isEmpty()); } //============================================================================================ KNMimeBase::UUParser::UUParser(const QCString &src, const QCString &subject) : s_rc(src), s_ubject(subject), p_artNr(-1), t_otalNr(-1) {} KNMimeBase::UUParser::~UUParser() {} bool KNMimeBase::UUParser::parse() { int beginPos=0, uuStart=0, endPos=0, lineCount=0, MCount=0, pos=0, len=0; bool containsBegin=false, containsEnd=false; QCString tmp; if( (beginPos=s_rc.find(QRegExp("begin [0-9][0-9][0-9]")))>-1 && (beginPos==0 || s_rc.at(beginPos-1)=='\n') ) { containsBegin=true; uuStart=s_rc.find('\n', beginPos); if(uuStart==-1) //no more line breaks found, we give up return false; else uuStart++; //points now at the beginning of the next line } else beginPos=0; if( (endPos=s_rc.findRev("\nend"))==-1 ) endPos=s_rc.length(); //no end found else { containsEnd=true; } //printf("beginPos=%d , uuStart=%d , endPos=%d\n", beginPos, uuStart, endPos); //all lines in a uuencoded text start with 'M' for(int idx=uuStart; idx5) return false; //too many "non-M-Lines" found, we give up if( (!containsBegin || !containsEnd) && s_ubject) { // message may be split up => parse subject pos=QRegExp("[0-9]+/[0-9]+").match(QString(s_ubject), 0, &len); if(pos!=-1) { tmp=s_ubject.mid(pos, len); pos=tmp.find('/'); p_artNr=tmp.left(pos).toInt(); t_otalNr=tmp.right(tmp.length()-pos-1).toInt(); } else return false; //no "part-numbers" found in the subject, we give up } //everything before "begin" is text if(beginPos>0) t_ext=s_rc.left(beginPos); if(containsBegin) f_ilename=s_rc.mid(beginPos+10, uuStart-beginPos-11); //everything between "begin ### " and the next LF is considered as the filename b_in=s_rc.mid(beginPos, endPos-beginPos+1); //everything beetween "begin" and "end" is uuencoded //try to guess the mimetype from the file-extension if(!f_ilename.isEmpty()) { pos=f_ilename.findRev('.'); if(pos++ != -1) { tmp=f_ilename.mid(pos, f_ilename.length()-pos).upper(); if(tmp=="JPG" || tmp=="JPEG") m_imeType="image/jpeg"; else if(tmp=="GIF") m_imeType="image/gif"; else if(tmp=="PNG") m_imeType="image/png"; else if(tmp=="TIFF" || tmp=="TIF") m_imeType="image/tiff"; else if(tmp=="XPM") m_imeType="image/x-xpm"; else if(tmp=="XBM") m_imeType="image/x-xbm"; else if(tmp=="BMP") m_imeType="image/x-bmp"; else if(tmp=="TXT" || tmp=="ASC" || tmp=="H" || tmp=="C" || tmp=="CC" || tmp=="CPP") m_imeType="text/plain"; else if(tmp=="HTML" || tmp=="HTM") m_imeType="text/html"; else m_imeType="application/octet-stream"; } } return true; } //============================================================================================ void KNMimeBase::BoolFlags::set(unsigned int i, bool b) { if(i>15) return; unsigned char p; //bitmask int n; if(i<8) { //first byte p=(1 << i); n=0; } else { //second byte p=(1 << i-8); n=1; } if(b) bits[n] = bits[n] | p; else bits[n] = bits[n] & (255-p); } bool KNMimeBase::BoolFlags::get(unsigned int i) { if(i>15) return false; unsigned char p; //bitmask int n; if(i<8) { //first byte p=(1 << i); n=0; } else { //second byte p=(1 << i-8); n=1; } return ( (bits[n] & p)>0 ); } //============================================================================================ KNMimeContent::KNMimeContent() : c_ontents(0), h_eaders(0), d_efaultCS(QFont::ISO_8859_1), f_orceDefaultCS(false) {} KNMimeContent::~KNMimeContent() { delete c_ontents; delete h_eaders; } void KNMimeContent::setContent(QStrList *l) { //qDebug("KNMimeContent::setContent(QStrList *l) : start"); h_ead.resize(0); b_ody.resize(0); //usage of textstreams is much faster than simply appending the strings QTextStream hts(h_ead, IO_WriteOnly), bts(b_ody, IO_WriteOnly); hts.setEncoding(QTextStream::Latin1); bts.setEncoding(QTextStream::Latin1); bool isHead=true; for(char *line=l->first(); line; line=l->next()) { if(isHead && line[0]=='\0') { isHead=false; continue; } if(isHead) hts << line << "\n"; else bts << line << "\n"; } //terminate strings hts << '\0'; bts << '\0'; //qDebug("KNMimeContent::setContent(QStrList *l) : finished"); } void KNMimeContent::setContent(const QCString &s) { int pos=s.find("\n\n", 0); if(pos>-1) { h_ead=s.left(++pos); //header *must* end with "\n" !! b_ody=s.mid(++pos, s.length()-pos); } else h_ead=s; } //parse the message, split multiple parts void KNMimeContent::parse() { qDebug("void KNMimeContent::parse() : start"); delete h_eaders; h_eaders=0; delete c_ontents; c_ontents=0; KNHeaders::ContentType *ct=contentType(); QCString tmp; KNMimeContent *c; KNHeaders::contentCategory cat; if(ct->isMultipart()) { //this is a multipart message tmp=ct->boundary(); //get boundary-parameter if(!tmp.isEmpty()) { MultiPartParser mpp(b_ody, tmp); if(mpp.parse()) { //at least one part found c_ontents=new List(); c_ontents->setAutoDelete(true); if(ct->isSubtype("alternative")) //examine category for the sub-parts cat=KNHeaders::CCalternativePart; else cat=KNHeaders::CCmixedPart; //default to "mixed" QCStringList parts=mpp.parts(); QCStringList::Iterator it; for(it=parts.begin(); it!=parts.end(); ++it) { //create a new KNMimeContent for every part c=new KNMimeContent(); c->setContent(*it); c->parse(); c->contentType()->setCategory(cat); //set category of the sub-part c_ontents->append(c); //qDebug("part:\n%s\n\n%s", c->h_ead.data(), c->b_ody.left(100).data()); } //the whole content is now split into single parts, so it's safe delete the message-body b_ody.resize(0); } else { //sh*t, the parsing failed so we have to treat the message as "text/plain" instead ct->setMimeType("text/plain"); ct->setCharset("US-ASCII"); } } } else if(ct->isText() && b_ody.size()>10000) { //large textual body => maybe an uuencoded binary? UUParser uup(b_ody, rawHeader("Subject")); if(uup.parse()) { // yep, it is uuencoded if(uup.isPartial()) { // this seems to be only a part of the message so we treat it as "message/partial" ct->setMimeType("message/partial"); //ct->setId(uniqueString()); not needed yet ct->setPartialParams(uup.partialCount(), uup.partialNumber()); contentTransferEncoding()->setCte(KNHeaders::CE7Bit); } else { //it's a complete message => treat as "multipart/mixed" cat=KNHeaders::CCmixedPart; ct->setMimeType("multipart/mixed"); //ct->setBoundary(multiPartBoundary()); not needed c_ontents=new List(); c_ontents->setAutoDelete(true); if(uup.hasTextPart()) { //there is plain text before the uuencoded part //text part c=new KNMimeContent(); //generate content with mime-compliant headers tmp="Content-Type: text/plain\nContent-Transfer-Encoding: 7Bit\n\n"+uup.textPart(); c->setContent(tmp); c->contentType()->setCategory(cat); c_ontents->append(c); } //binary part c=new KNMimeContent(); //generate content with mime-compliant headers tmp="Content-Type: "+uup.mimeType()+"; name=\""+uup.filename()+ "\"\nContent-Transfer-Encoding: x-uuencode\nContent-Disposition: attachment\n\n"+uup.binaryPart(); c->setContent(tmp); c->contentType()->setCategory(cat); c_ontents->append(c); //the whole content is now split into single parts, so it's safe to delete the message-body b_ody.resize(0); } } } qDebug("void KNMimeContent::parse() : finished"); } void KNMimeContent::assemble() { if(type()==ATmimeContent) h_ead=""; //body-parts do not get the "MIME-Version" header else h_ead+="MIME-Version: 1.0\n"; //Content-Type h_ead+=contentType()->as7BitString()+"\n"; //Content-Transfer-Encoding h_ead+=contentTransferEncoding()->as7BitString()+"\n"; if(type()==ATmimeContent) { //Content-Description KNHeaders::Base *h=contentDescription(false); if(h) h_ead+=h->as7BitString()+"\n"; //Content-Disposition h=contentDisposition(false); if(h) h_ead+=h->as7BitString()+"\n"; } } void KNMimeContent::clear() { delete h_eaders; h_eaders=0; delete c_ontents; c_ontents=0; h_ead.resize(0); b_ody.resize(0); } QCString KNMimeContent::encodedContent(bool useCrLf) { QCString e; //head e=h_ead.copy(); e+="\n"; //body if(!b_ody.isEmpty()) { //this message contains only one part KNHeaders::CTEncoding *enc=contentTransferEncoding(); if(enc->needToEncode()) { DwString dwsrc, dwdest; dwsrc=b_ody.data(); if(enc->cte()==KNHeaders::CEquPr) DwEncodeQuotedPrintable(dwsrc, dwdest); else DwEncodeBase64(dwsrc, dwdest); e+=dwdest.c_str(); } else e+=b_ody; } else if(c_ontents && !c_ontents->isEmpty()) { //this is a multipart message KNHeaders::ContentType *ct=contentType(); QCString boundary="--"+ct->boundary(); //add all (encoded) contents separated by boundaries for(KNMimeContent *c=c_ontents->first(); c; c=c_ontents->next()) { e+=boundary+"\n"; e+=c->encodedContent(useCrLf); } //finally append the closing boundary e+=boundary+"--\n"; }; if(useCrLf) return LFtoCRLF(e); else return e; } QByteArray KNMimeContent::decodedContent() { QByteArray ret; KNHeaders::CTEncoding *ec=contentTransferEncoding(); if(ec->decoded()) ret=b_ody; else { DwString dwsrc, dwdest; dwsrc=b_ody.data(); DwUuencode dwuu; switch(ec->cte()) { case KNHeaders::CEbase64 : DwDecodeBase64(dwsrc, dwdest); break; case KNHeaders::CEquPr : DwDecodeQuotedPrintable(dwsrc, dwdest); break; case KNHeaders::CEuuenc : dwuu.SetAsciiChars(dwsrc); dwuu.Decode(); dwdest=dwuu.BinaryChars(); break; default : dwdest=dwsrc; } ret.duplicate(dwdest.data(), dwdest.size()); } return ret; } void KNMimeContent::decodedText(QString &s) { if(!decodeText()) //this is not a text content !! return; bool ok=true; QTextCodec *codec=KGlobal::charsets()->codecForName(contentType()->charset(),ok); s=codec->toUnicode(b_ody.data(), b_ody.length()); } void KNMimeContent::decodedText(QStringList &l) { if(!decodeText()) //this is not a text content !! return; QString unicode; bool ok=true; QTextCodec *codec=KGlobal::charsets()->codecForName(contentType()->charset(),ok); unicode=codec->toUnicode(b_ody.data(), b_ody.length()); l=QStringList::split("\n", unicode, true); //split the string at linebreaks } bool KNMimeContent::canDecode8BitText() { bool ok=true; (void) KGlobal::charsets()->codecForName(contentType()->charset(),ok); return ok; } void KNMimeContent::setFontForContent(QFont &f) { KCharsets *c=KGlobal::charsets(); QFont::CharSet cs; cs=c->nameToID(contentType()->charset()); c->setQFont(f, cs); } void KNMimeContent::fromUnicodeString(const QString &s) { bool ok=true; QTextCodec *codec=KGlobal::charsets()->codecForName(contentType()->charset(),ok); if(!ok) { // no suitable codec found => try local settings and hope the best ;-) codec=KGlobal::charsets()->codecForName(KGlobal::locale()->charset(),ok); QCString chset=knGlobals.cfgManager->postNewsTechnical()->findComposerCharset(KGlobal::locale()->charset().latin1()); if (chset.isEmpty()) chset=KGlobal::locale()->charset().latin1(); contentType()->setCharset(chset); } b_ody=codec->fromUnicode(s); contentTransferEncoding()->setDecoded(true); //text is always decoded } KNMimeContent* KNMimeContent::textContent() { KNMimeContent *ret=0; //return the first content with mimetype=text/* if(contentType()->isText()) ret=this; else if(c_ontents) for(KNMimeContent *c=c_ontents->first(); c; c=c_ontents->next()) if( (ret=c->textContent())!=0 ) break; return ret; } void KNMimeContent::attachments(KNMimeContent::List *dst, bool incAlternatives) { dst->setAutoDelete(false); //don't delete the contents if(!c_ontents) dst->append(this); else { for(KNMimeContent *c=c_ontents->first(); c; c=c_ontents->next()) { if( !incAlternatives && c->contentType()->category()==KNHeaders::CCalternativePart) continue; else c->attachments(dst, incAlternatives); } } if(type()!=ATmimeContent) { // this is the toplevel article KNMimeContent *text=textContent(); if(text) dst->removeRef(text); } } void KNMimeContent::addContent(KNMimeContent *c, bool prepend) { if(!c_ontents) { // this message is not multipart yet c_ontents=new List(); c_ontents->setAutoDelete(true); // first we convert the body to a content KNMimeContent *main=new KNMimeContent(); //the Mime-Headers are needed, so we move them to the new content if(h_eaders) { main->h_eaders=new KNHeaders::List(); main->h_eaders->setAutoDelete(true); KNHeaders::List srcHdrs=(*h_eaders); srcHdrs.setAutoDelete(false); int idx=0; for(KNHeaders::Base *h=srcHdrs.first(); h; h=srcHdrs.next()) { if(h->isMimeHeader()) { //remove from this content idx=h_eaders->findRef(h); h_eaders->take(idx); //append to new content main->h_eaders->append(h); } } } //"main" is now part of a multipart/mixed message main->contentType()->setCategory(KNHeaders::CCmixedPart); //the head of "main" is empty, so we assemble it main->assemble(); //now we can copy the body and append the new content; main->b_ody=b_ody.copy(); c_ontents->append(main); b_ody.resize(0); //not longer needed //finally we have to convert this article to "multipart/mixed" KNHeaders::ContentType *ct=contentType(); ct->setMimeType("multipart/mixed"); ct->setBoundary(multiPartBoundary()); ct->setCategory(KNHeaders::CCcontainer); contentTransferEncoding()->clear(); // 7Bit, decoded } //here we actually add the content if(prepend) c_ontents->insert(0, c); else c_ontents->append(c); } void KNMimeContent::removeContent(KNMimeContent *c, bool del) { if(!c_ontents) // what the .. return; int idx=0; if(del) c_ontents->removeRef(c); else { idx=c_ontents->findRef(c); c_ontents->take(idx); } //only one content left => turn this message in a single-part if(c_ontents->count()==1) { KNMimeContent *main=c_ontents->first(); //first we have to move the mime-headers if(main->h_eaders) { if(!h_eaders) { h_eaders=new KNHeaders::List(); h_eaders->setAutoDelete(true); } KNHeaders::List mainHdrs=(*(main->h_eaders)); mainHdrs.setAutoDelete(false); for(KNHeaders::Base *h=mainHdrs.first(); h; h=mainHdrs.next()) { if(h->isMimeHeader()) { removeHeader(h->type()); //remove the old header first h_eaders->append(h); //now append the new one idx=main->h_eaders->findRef(h); main->h_eaders->take(idx); //remove from the old content kdDebug(5003) << "KNMimeContent::removeContent(KNMimeContent *c, bool del) : mime-header moved: " << h->as7BitString() << endl; } } } //now we can copy the body b_ody=main->b_ody.copy(); //finally we can delete the content list delete c_ontents; c_ontents=0; } } void KNMimeContent::changeEncoding(KNHeaders::contentEncoding e) { KNHeaders::CTEncoding *enc=contentTransferEncoding(); if(enc->cte()==e) //nothing to do return; if(decodeText()) enc->setCte(e); // text is not encoded until it's sent or saved so we just set the new encoding else { // this content contains non textual data, that has to be re-encoded if(e!=KNHeaders::CEbase64) { //kdWarning(5003) << "KNMimeContent::changeEncoding() : non textual data and encoding != base64 - this should not happen\n => forcing base64" << endl; e=KNHeaders::CEbase64; } if(enc->cte()!=e) { // ok, we reencode the content using base64 DwString dwsrc, dwdest; QByteArray d=decodedContent(); //decode content dwsrc.assign(d.data(), d.size()); DwEncodeBase64(dwsrc, dwdest); //encode as base64 b_ody=dwdest.c_str(); //set body enc->setCte(e); //set encoding enc->setDecoded(false); } } } void KNMimeContent::toStream(QTextStream &ts) { ts << encodedContent(false); } KNHeaders::Base* KNMimeContent::getHeaderByType(const char *type) { if(!type) return 0; KNHeaders::Base *h=0; //first we check if the requested header is already cached if(h_eaders) for(h=h_eaders->first(); h; h=h_eaders->next()) if(h->is(type)) return h; //found //now we look for it in the article head QCString raw=rawHeader(type); if(!raw.isEmpty()) { //ok, we found it //choose a suitable header class if(strcasecmp("Message-Id", type)==0) h=new KNHeaders::MessageID(raw); else if(strcasecmp("Subject", type)==0) h=new KNHeaders::Subject(raw, d_efaultCS, f_orceDefaultCS); else if(strcasecmp("Date", type)==0) h=new KNHeaders::Date(raw); else if(strcasecmp("From", type)==0) h=new KNHeaders::From(raw, d_efaultCS, f_orceDefaultCS); else if(strcasecmp("Organization", type)==0) h=new KNHeaders::Organization(raw, d_efaultCS, f_orceDefaultCS); else if(strcasecmp("Reply-To", type)==0) h=new KNHeaders::ReplyTo(raw, d_efaultCS, f_orceDefaultCS); else if(strcasecmp("To", type)==0) h=new KNHeaders::To(raw, d_efaultCS, f_orceDefaultCS); else if(strcasecmp("CC", type)==0) h=new KNHeaders::CC(raw, d_efaultCS, f_orceDefaultCS); else if(strcasecmp("BCC", type)==0) h=new KNHeaders::BCC(raw, d_efaultCS, f_orceDefaultCS); else if(strcasecmp("Newsgroups", type)==0) h=new KNHeaders::Newsgroups(raw); else if(strcasecmp("Followup-To", type)==0) h=new KNHeaders::FollowUpTo(raw); else if(strcasecmp("References", type)==0) h=new KNHeaders::References(raw); else if(strcasecmp("Lines", type)==0) h=new KNHeaders::Lines(raw); else if(strcasecmp("Content-Type", type)==0) h=new KNHeaders::ContentType(raw, d_efaultCS, f_orceDefaultCS); else if(strcasecmp("Content-Transfer-Encoding", type)==0) h=new KNHeaders::CTEncoding(raw); else if(strcasecmp("Content-Disposition", type)==0) h=new KNHeaders::CDisposition(raw, d_efaultCS, f_orceDefaultCS); else if(strcasecmp("Content-Description", type)==0) h=new KNHeaders::CDescription(raw, d_efaultCS, f_orceDefaultCS); else h=new KNHeaders::Generic(type, raw, d_efaultCS, f_orceDefaultCS); if(!h_eaders) { h_eaders=new KNHeaders::List(); h_eaders->setAutoDelete(true); } h_eaders->append(h); //add to cache return h; } else return 0; //header not found } void KNMimeContent::setHeader(KNHeaders::Base *h) { if(!h) return; removeHeader(h->type()); if(!h_eaders) { h_eaders=new KNHeaders::List(); h_eaders->setAutoDelete(true); } h_eaders->append(h); } bool KNMimeContent::removeHeader(const char *type) { if(h_eaders) for(KNHeaders::Base *h=h_eaders->first(); h; h=h_eaders->next()) if(h->is(type)) return h_eaders->remove(); return false; } int KNMimeContent::lineCount() { int ret=0; if(type()==ATmimeContent) ret+=h_ead.contains('\n'); ret+=b_ody.contains('\n'); if(c_ontents && !c_ontents->isEmpty()) for(KNMimeContent *c=c_ontents->first(); c; c=c_ontents->next()) ret+=c->lineCount(); return ret; } QCString KNMimeContent::rawHeader(const char *name) { QCString n=QCString(name)+": "; int pos1=h_ead.find(n, 0, false), pos2=0, len=h_ead.length()-1; if(pos1>-1 && (pos1==0 || h_ead[pos1-1]=='\n')) { //there is a header with the given name QCString tmp=h_ead.mid(pos1, h_ead.length()-pos1); pos1+=n.length(); //skip the name pos2=pos1; while(1) { pos2=h_ead.find("\n", pos2+1); if(pos2==-1 || pos2==len || ( h_ead[pos2+1]!=' ' && h_ead[pos2+1]!='\t') ) //break if we reach the end of the string, honor folded lines break; } if(pos2<0) pos2=len+1; //take the rest of the string return h_ead.mid(pos1, pos2-pos1).simplifyWhiteSpace(); } else return QCString(); //header not found } bool KNMimeContent::decodeText() { KNHeaders::CTEncoding *enc=contentTransferEncoding(); if(enc->decoded()) return true; //nothing to do if(!contentType()->isText()) return false; //non textual data cannot be decoded here => use decodedContent() instead DwString dwsrc=b_ody.data(), dwdest; if(enc->cte()==KNHeaders::CEquPr) DwDecodeQuotedPrintable(dwsrc, dwdest); else DwDecodeBase64(dwsrc, dwdest); b_ody=dwdest.c_str(); enc->setDecoded(true); return true; } void KNMimeContent::setForceDefaultCS(bool b) { f_orceDefaultCS=b; if (h_eaders) h_eaders->clear(); parse(); } //========================================================================================== KNArticle::KNArticle(KNArticleCollection *c) { i_d=-1; i_tem=0; c_ol=c; } KNArticle::~KNArticle() { delete i_tem; } void KNArticle::parse() { KNMimeContent::parse(); QCString raw; if(s_ubject.isEmpty()) { raw=rawHeader(s_ubject.type()); if(!raw.isEmpty()) s_ubject.from7BitString(raw, d_efaultCS, f_orceDefaultCS); } if(d_ate.isEmpty()) { raw=rawHeader(d_ate.type()); if(!raw.isEmpty()) d_ate.from7BitString(raw, d_efaultCS, f_orceDefaultCS); } } void KNArticle::assemble() { KNHeaders::Base *h; h_ead=""; //Message-ID if( (h=messageID(false))!=0 ) h_ead+=h->as7BitString()+"\n"; //Control if( (h=control(false))!=0 ) h_ead+=h->as7BitString()+"\n"; //Supersedes if( (h=supersedes(false))!=0 ) h_ead+=h->as7BitString()+"\n"; //From if( (h=from(false))!=0 ) h_ead+=h->as7BitString()+"\n"; //Subject if( (h=subject(false))!=0 ) h_ead+=h->as7BitString()+"\n"; //To if( (h=to(false))!=0 ) h_ead+=h->as7BitString()+"\n"; //Newsgroups if( (h=newsgroups(false))!=0 ) h_ead+=h->as7BitString()+"\n"; //Followup-To if( (h=followUpTo(false))!=0 ) h_ead+=h->as7BitString()+"\n"; //Reply-To if( (h=replyTo(false))!=0 ) h_ead+=h->as7BitString()+"\n"; //Date if( (h=date(false))!=0 ) h_ead+=h->as7BitString()+"\n"; //References if( (h=references(false))!=0 ) h_ead+=h->as7BitString()+"\n"; //Lines if( (h=lines(false))!=0 ) h_ead+=h->as7BitString()+"\n"; //Organization if( (h=organization(false))!=0 ) h_ead+=h->as7BitString()+"\n"; //User-Agent if( (h=userAgent(false))!=0 ) h_ead+=h->as7BitString()+"\n"; //Mime-Headers KNMimeContent::assemble(); //X-Headers if(h_eaders && !h_eaders->isEmpty()) { for(h=h_eaders->first(); h; h=h_eaders->next()) { if( h->isXHeader() && (strncasecmp(h->type(), "X-KNode", 7)!=0) ) h_ead+=h->as7BitString()+"\n"; } } } void KNArticle::clear() { s_ubject.clear(); d_ate.clear(); l_ines.clear(); f_lags.clear(); KNMimeContent::clear(); } KNHeaders::Base* KNArticle::getHeaderByType(const char *type) { if(strcasecmp("Subject", type)==0) { if(s_ubject.isEmpty()) return 0; else return &s_ubject; } else if(strcasecmp("Date", type)==0){ if(d_ate.isEmpty()) return 0; else return &d_ate; } else if(strcasecmp("Lines", type)==0) { if(l_ines.isEmpty()) return 0; else return &l_ines; } else return KNMimeContent::getHeaderByType(type); } void KNArticle::setHeader(KNHeaders::Base *h) { if(h->is("Subject")) s_ubject.fromUnicodeString(h->asUnicodeString(), h->rfc2047Charset()); else if(h->is("Date")) d_ate.setUnixTime( (static_cast(h))->unixTime() ); else if(h->is("Lines")) l_ines.setNumberOfLines( (static_cast(h))->numberOfLines() ); else return KNMimeContent::setHeader(h); } bool KNArticle::removeHeader(const char *type) { if(strcasecmp("Subject", type)==0) s_ubject.clear(); else if(strcasecmp("Date", type)==0) d_ate.clear(); else if(strcasecmp("Lines", type)==0) l_ines.clear(); else return KNMimeContent::removeHeader(type); return true; } void KNArticle::setListItem(KNHdrViewItem *it) { i_tem=it; if(i_tem) i_tem->art=this; } void KNArticle::setLocked(bool b) { f_lags.set(0, b); if(c_ol) { // local articles may have c_ol==0 ! if(b) c_ol->articleLocked(); else c_ol->articleUnlocked(); } } void KNArticle::setForceDefaultCS(bool b) { s_ubject.clear(); d_ate.clear(); l_ines.clear(); KNMimeContent::setForceDefaultCS(b); } //========================================================================================= KNRemoteArticle::KNRemoteArticle(KNGroup *g) : KNArticle(g), i_dRef(-1), t_hrLevel(0), s_core(50), u_nreadFups(0), n_ewFups(0) { if (g->useCharset()) d_efaultCS = KGlobal::charsets()->charsetForEncoding(g->defaultCharset()); else d_efaultCS = KGlobal::charsets()->charsetForEncoding(knGlobals.cfgManager->postNewsTechnical()->charset()); } KNRemoteArticle::~KNRemoteArticle() {} void KNRemoteArticle::parse() { KNArticle::parse(); QCString raw; if(m_essageID.isEmpty() && !(raw=rawHeader(m_essageID.type())).isEmpty() ) m_essageID.from7BitString(raw, d_efaultCS, f_orceDefaultCS); if(f_rom.isEmpty() && !(raw=rawHeader(f_rom.type())).isEmpty() ) f_rom.from7BitString(raw, d_efaultCS, f_orceDefaultCS); if(l_ines.isEmpty() && !(raw=rawHeader(l_ines.type())).isEmpty() ) l_ines.from7BitString(raw, d_efaultCS, f_orceDefaultCS); } void KNRemoteArticle::clear() { m_essageID.clear(); f_rom.clear(); KNArticle::clear(); } KNHeaders::Base* KNRemoteArticle::getHeaderByType(const char *type) { if(strcasecmp("Message-ID", type)==0) { if(m_essageID.isEmpty()) return 0; else return &m_essageID; } else if(strcasecmp("From", type)==0) { if(f_rom.isEmpty()) return 0; else return &f_rom; } else return KNArticle::getHeaderByType(type); } void KNRemoteArticle::setHeader(KNHeaders::Base *h) { if(h->is("Message-ID")) m_essageID.from7BitString(h->as7BitString(false), d_efaultCS, f_orceDefaultCS); else if(h->is("From")) { f_rom.setEmail( (static_cast(h))->email() ); f_rom.setName( (static_cast(h))->name() ); } else KNArticle::setHeader(h); } bool KNRemoteArticle::removeHeader(const char *type) { if(strcasecmp("Message-ID", type)==0) m_essageID.clear(); else if(strcasecmp("From", type)==0) f_rom.clear(); else return KNArticle::removeHeader(type); return true; } void KNRemoteArticle::initListItem() { i_tem->setText(0, s_ubject.asUnicodeString()); i_tem->subjectCS = s_ubject.rfc2047Charset(); + if(f_rom.hasName()) i_tem->setText(1, f_rom.name()); else i_tem->setText(1, QString(f_rom.email())); i_tem->nameCS = f_rom.rfc2047Charset(); - i_tem->setText(3, KGlobal::locale()->formatDateTime(d_ate.qdt(), true)); + i_tem->setText(3, QString("%1").arg(lines()->numberOfLines(),3)); + + i_tem->setText(4, KGlobal::locale()->formatDateTime(d_ate.qdt(), true)); updateListItem(); } void KNRemoteArticle::updateListItem() { if(!i_tem) return; KNConfig::Appearance *app=knGlobals.cfgManager->appearance(); if(isRead()) { if(hasContent()) i_tem->setPixmap(0, app->icon(KNConfig::Appearance::greyBallChkd)); else i_tem->setPixmap(0, app->icon(KNConfig::Appearance::greyBall)); } else { if(hasContent()) i_tem->setPixmap(0,app->icon(KNConfig::Appearance::redBallChkd)); else i_tem->setPixmap(0, app->icon(KNConfig::Appearance::redBall)); } if(hasNewFollowUps()) i_tem->setPixmap(1, app->icon(KNConfig::Appearance::newFups)); else i_tem->setPixmap(1, app->icon(KNConfig::Appearance::null)); if(s_core==100) i_tem->setPixmap(2, app->icon(KNConfig::Appearance::eyes)); else i_tem->setPixmap(2, app->icon(KNConfig::Appearance::null)); i_tem->setText(2, QString("%1").arg(s_core,3)); i_tem->setExpandable( (threadMode() && hasVisibleFollowUps()) ); i_tem->repaint(); //force repaint } void KNRemoteArticle::thread(KNRemoteArticle::List *l) { KNRemoteArticle *tmp=0, *ref=this; KNGroup *g=static_cast(c_ol); int idRef=i_dRef, topID=-1; while(idRef!=0) { ref=g->byId(idRef); if(!ref) return; // sh#t !! idRef=ref->idRef(); } topID=ref->id(); l->append(ref); for(int i=0; ilength(); i++) { tmp=g->at(i); if(tmp->idRef()!=0) { idRef=tmp->idRef(); while(idRef!=0) { ref=g->byId(idRef); idRef=ref->idRef(); } if(ref->id()==topID) l->append(tmp); } } } void KNRemoteArticle::setForceDefaultCS(bool b) { if (!b) { // restore default KNGroup *g=static_cast(c_ol); if (g->useCharset()) d_efaultCS = KGlobal::charsets()->charsetForEncoding(g->defaultCharset()); else d_efaultCS = KGlobal::charsets()->charsetForEncoding(knGlobals.cfgManager->postNewsTechnical()->charset()); } m_essageID.clear(); f_rom.clear(); KNArticle::setForceDefaultCS(b); initListItem(); } //========================================================================================= KNLocalArticle::KNLocalArticle(KNArticleCollection *c) : KNArticle(c), s_Offset(-1), e_Offset(-1), s_erverId(-1) { d_efaultCS = KGlobal::charsets()->charsetForEncoding(knGlobals.cfgManager->postNewsTechnical()->charset()); } KNLocalArticle::~KNLocalArticle() {} void KNLocalArticle::parse() { KNArticle::parse(); QCString raw; if(n_ewsgroups.isEmpty() && !(raw=rawHeader(n_ewsgroups.type())).isEmpty() ) n_ewsgroups.from7BitString(raw, d_efaultCS, f_orceDefaultCS); if(t_o.isEmpty() && !(raw=rawHeader(t_o.type())).isEmpty() ) t_o.from7BitString(raw, d_efaultCS, f_orceDefaultCS); } void KNLocalArticle::clear() { KNArticle::clear(); n_ewsgroups.clear(); t_o.clear(); } KNHeaders::Base* KNLocalArticle::getHeaderByType(const char *type) { if(strcasecmp("Newsgroups", type)==0) { if(!doPost() || n_ewsgroups.isEmpty()) return 0; else return &n_ewsgroups; } else if(strcasecmp("To", type)==0) { if(!doMail() || t_o.isEmpty()) return 0; else return &t_o; } else return KNArticle::getHeaderByType(type); } void KNLocalArticle::setHeader(KNHeaders::Base *h) { if(h->is("To")) t_o.from7BitString(h->as7BitString(false), d_efaultCS, f_orceDefaultCS); else if(h->is("Newsgroups")) n_ewsgroups.from7BitString(h->as7BitString(false), d_efaultCS, f_orceDefaultCS); else return KNArticle::setHeader(h); } bool KNLocalArticle::removeHeader(const char *type) { if(strcasecmp("To", type)==0) t_o.clear(); else if(strcasecmp("Newsgroups", type)==0) n_ewsgroups.clear(); else return KNArticle::removeHeader(type); return true; } void KNLocalArticle::updateListItem() { if(!i_tem) return; i_tem->setText(0, s_ubject.asUnicodeString()); i_tem->subjectCS = s_ubject.rfc2047Charset(); QString tmp; int idx=0; KNConfig::Appearance *app=knGlobals.cfgManager->appearance(); if(doPost()) { tmp+=n_ewsgroups.asUnicodeString(); i_tem->nameCS = n_ewsgroups.rfc2047Charset(); if(canceled()) i_tem->setPixmap(idx++, app->icon(KNConfig::Appearance::canceledPosting)); else i_tem->setPixmap(idx++, app->icon(KNConfig::Appearance::posting)); } if(doMail()) { i_tem->setPixmap(idx++, app->icon(KNConfig::Appearance::mail)); if(doPost()) tmp+=" / "; tmp+=t_o.asUnicodeString(); i_tem->nameCS = t_o.rfc2047Charset(); } i_tem->setText(1, tmp); i_tem->setText(2, QString::null); - i_tem->setText(3, KGlobal::locale()->formatDateTime(d_ate.qdt(), true)); + if (lines()->numberOfLines()!=-1) + i_tem->setText(3, QString("%1").arg(lines()->numberOfLines(),3)); + else + i_tem->setText(3, QString::null); + i_tem->setText(4, KGlobal::locale()->formatDateTime(d_ate.qdt(), true)); } void KNLocalArticle::setForceDefaultCS(bool b) { if (!b) // restore default d_efaultCS = KGlobal::charsets()->charsetForEncoding(knGlobals.cfgManager->postNewsTechnical()->charset()); n_ewsgroups.clear(); t_o.clear(); KNArticle::setForceDefaultCS(b); updateListItem(); } //========================================================================================= KNAttachment::KNAttachment(KNMimeContent *c) : c_ontent(c), i_sAttached(true), h_asChanged(false) { KNHeaders::ContentType *t=c->contentType(); KNHeaders::CTEncoding *e=c->contentTransferEncoding(); KNHeaders::CDescription *d=c->contentDescription(false); n_ame=t->name(); setMimeType(t->mimeType()); if(d) d_escription=d->asUnicodeString(); e_ncoding.setCte(e->cte()); } KNAttachment::KNAttachment(const QString &path) : c_ontent(0), i_sAttached(false), h_asChanged(true) { setMimeType((KMimeMagic::self()->findFileType(path))->mimeType()); f_ile.setName(path); n_ame=QFileInfo(f_ile).fileName(); } KNAttachment::~KNAttachment() { if(!i_sAttached && c_ontent) delete c_ontent; } void KNAttachment::setMimeType(const QString &s) { m_imeType=s.latin1(); h_asChanged=true; if(m_imeType.find("text/", 0, false)==-1) { f_b64=true; e_ncoding.setCte(KNHeaders::CEbase64); } else { f_b64=false; if (knGlobals.cfgManager->postNewsTechnical()->allow8BitBody()) setCte(KNHeaders::CE8Bit); else setCte(KNHeaders::CEquPr); } } QString KNAttachment::contentSize() { QString ret; int s=0; if(c_ontent && c_ontent->hasContent()) s=c_ontent->size(); else s=f_ile.size(); if(s > 1023) { s=s/1024; ret.setNum(s); ret+=" kB"; } else { ret.setNum(s); ret+=" Bytes"; } return ret; } void KNAttachment::updateContentInfo() { if(!h_asChanged) return; //Content-Type KNHeaders::ContentType *t=c_ontent->contentType(); t->setMimeType(m_imeType); t->setName(n_ame, KGlobal::charsets()->charsetForLocale()); t->setCategory(KNHeaders::CCmixedPart); //Content-Description if(d_escription.isEmpty()) c_ontent->removeHeader("Content-Description"); else c_ontent->contentDescription()->fromUnicodeString(d_escription, KGlobal::charsets()->charsetForLocale()); //Content-Disposition KNHeaders::CDisposition *d=c_ontent->contentDisposition(); d->setDisposition(KNHeaders::CDattachment); d->setFilename(n_ame); //Content-Transfer-Encoding if(i_sAttached) c_ontent->changeEncoding(e_ncoding.cte()); else c_ontent->contentTransferEncoding()->setCte(e_ncoding.cte()); c_ontent->assemble(); } void KNAttachment::attach(KNMimeContent *c) { if(i_sAttached || f_ile.name().isEmpty()) return; if(!f_ile.open(IO_ReadOnly)) { displayExternalFileError(); i_sAttached=false; return; } c_ontent=new KNMimeContent(); updateContentInfo(); KNHeaders::ContentType *type=c_ontent->contentType(); KNHeaders::CTEncoding *e=c_ontent->contentTransferEncoding(); if(e_ncoding.cte()==KNHeaders::CEbase64 || !type->isText()) { //encode base64 char *buff=new char[5710]; int readBytes=0; DwString dest; DwString src; QCString data( (f_ile.size()*4/3)+10 ); data.at(0)='\0'; while(!f_ile.atEnd()) { // read 5700 bytes at once : // 76 chars per line * 6 bit per char / 8 bit per byte => 57 bytes per line // we append 100 lines in a row => encode 5700 bytes readBytes=f_ile.readBlock(buff, 5700); if(readBytes<5700 && f_ile.status()!=IO_Ok) { displayExternalFileError(); f_ile.close(); delete c_ontent; c_ontent=0; break; } src.assign(buff, readBytes); DwEncodeBase64(src, dest); data+=dest.c_str(); } f_ile.close(); delete[] buff; c_ontent->b_ody=data; e->setCte(KNHeaders::CEbase64); e->setDecoded(false); } else { //do not encode text QCString txt(f_ile.size()+10); int readBytes=f_ile.readBlock(txt.data(), f_ile.size()); f_ile.close(); if(readBytes<(int)f_ile.size() && f_ile.status()!=IO_Ok) { displayExternalFileError(); delete c_ontent; c_ontent=0; } else { c_ontent->b_ody=txt; c_ontent->contentTransferEncoding()->setDecoded(true); } } if(c_ontent) { c->addContent(c_ontent); i_sAttached=true; } } void KNAttachment::detach(KNMimeContent *c) { if(i_sAttached) { c->removeContent(c_ontent, false); i_sAttached=false; } } diff --git a/knode/knodeview.cpp b/knode/knodeview.cpp index f0bc9d1a7c..bafc467285 100644 --- a/knode/knodeview.cpp +++ b/knode/knodeview.cpp @@ -1,1393 +1,1412 @@ /* knodeview.cpp KNode, the KDE newsreader Copyright (c) 1999-2000 the KNode authors. See file AUTHORS for details This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, US */ #include #include #include #include #include #include #include #include #include //GUI #include "knodeview.h" #include "knode.h" #include "knarticlewidget.h" #include "knarticlewindow.h" #include "knscoredialog.h" #include "kncollectionviewitem.h" #include "knhdrviewitem.h" #include "knfocuswidget.h" //Core #include "knglobals.h" #include "knconfigmanager.h" #include "knarticlemanager.h" #include "knarticlefactory.h" #include "kngroup.h" #include "kngroupmanager.h" #include "knnntpaccount.h" #include "knaccountmanager.h" #include "knnetaccess.h" #include "knfiltermanager.h" #include "knfoldermanager.h" #include "knfolder.h" #include "kncleanup.h" KNodeView::KNodeView(KNMainWindow *w, const char * name) : QSplitter(w, name), l_ongView(true), b_lockui(false), s_electedAccount(0), s_electedGroup(0), s_electedFolder(0), s_electedArticle(0), a_ctions(w->actionCollection()) { //------------------------------- ---------------------------------- c_fgManager=new KNConfigManager(); knGlobals.cfgManager=c_fgManager; //------------------------------- ---------------------------------- //-------------------------------- ------------------------------------ setOpaqueResize(true); //collection view c_olFocus=new KNFocusWidget(this,"colFocus"); c_olView=new KNListView(c_olFocus,"collectionView"); c_olFocus->setWidget(c_olView); setResizeMode(c_olFocus, QSplitter::KeepSize); c_olView->setFrameStyle(QFrame::Panel | QFrame::Sunken); c_olView->setTreeStepSize(12); c_olView->setRootIsDecorated(true); c_olView->setShowSortIndicator(true); c_olView->addColumn(i18n("Name"),162); c_olView->addColumn(i18n("Total"),36); c_olView->addColumn(i18n("Unread"),48); c_olView->setColumnAlignment(1,AlignCenter); c_olView->setColumnAlignment(2,AlignCenter); connect(c_olView, SIGNAL(itemSelected(QListViewItem*)), this, SLOT(slotCollectionSelected(QListViewItem*))); connect(c_olView, SIGNAL(rightButtonPressed(QListViewItem*, const QPoint&, int)), this, SLOT(slotCollectionRMB(QListViewItem*, const QPoint&, int))); //secondary splitter s_ecSplitter=new QSplitter(QSplitter::Vertical,this,"secSplitter"); s_ecSplitter->setOpaqueResize(true); //header view h_drFocus=new KNFocusWidget(s_ecSplitter,"hdrFocus"); h_drView=new KNListView(h_drFocus,"hdrView"); h_drFocus->setWidget(h_drView); s_ecSplitter->setResizeMode(h_drFocus, QSplitter::KeepSize); h_drView->setFrameStyle(QFrame::Panel | QFrame::Sunken); h_drView->setShowSortIndicator(true); h_drView->setRootIsDecorated(true); h_drView->addColumn(i18n("Subject"),207); h_drView->addColumn(i18n("From"),115); h_drView->addColumn(i18n("Score"),42); - h_drView->addColumn(i18n("Date (Time)"),102); - h_drView->setColumnAlignment(2, AlignCenter); + h_drView->addColumn(i18n("Lines"),42); + h_drView->addColumn(i18n("Date"),102); connect(h_drView, SIGNAL(itemSelected(QListViewItem*)), this, SLOT(slotArticleSelected(QListViewItem*))); connect(h_drView, SIGNAL(doubleClicked(QListViewItem*)), this, SLOT(slotArticleDoubleClicked(QListViewItem*))); connect(h_drView, SIGNAL(rightButtonPressed(QListViewItem*, const QPoint&, int)), this, SLOT(slotArticleRMB(QListViewItem*, const QPoint&, int))); connect(h_drView, SIGNAL(sortingChanged(int)), this, SLOT(slotHdrViewSortingChanged(int))); //article view a_rtFocus=new KNFocusWidget(s_ecSplitter,"artFocus"); a_rtView=new KNArticleWidget(a_ctions, a_rtFocus,"artView"); a_rtFocus->setWidget(a_rtView); //tab order setTabOrder(h_drView, a_rtView); setTabOrder(a_rtView, c_olView); //actions initActions(); //-------------------------------- ------------------------------------ //-------------------------------- ------------------------------------ //Network n_etAccess=new KNNetAccess(); connect(n_etAccess, SIGNAL(netActive(bool)), this, SLOT(slotNetworkActive(bool))); knGlobals.netAccess=n_etAccess; //Filter Manager f_ilManager=new KNFilterManager(a_ctArtFilter); knGlobals.filManager=f_ilManager; //Article Manager a_rtManager=new KNArticleManager(h_drView, f_ilManager); knGlobals.artManager=a_rtManager; //Group Manager g_rpManager=new KNGroupManager(a_rtManager); knGlobals.grpManager=g_rpManager; //Folder Manager f_olManager=new KNFolderManager(c_olView, a_rtManager); knGlobals.folManager=f_olManager; //Account Manager a_ccManager=new KNAccountManager(g_rpManager, c_olView); knGlobals.accManager=a_ccManager; //Article Factory a_rtFactory=new KNArticleFactory(f_olManager, g_rpManager); knGlobals.artFactory=a_rtFactory; //-------------------------------- ----------------------------------- //apply saved options readOptions(); //apply configuration configChanged(); // open all accounts that were open on the last shutdown KNNntpAccount *acc; for (acc=knGlobals.accManager->first(); acc; acc=knGlobals.accManager->next()) if( acc->wasOpen() && acc->listItem() ) acc->listItem()->setOpen(true); } KNodeView::~KNodeView() { saveOptions(); h_drView->clear(); //avoid some random crashes in KNHdrViewItem::~KNHdrViewItem() delete n_etAccess; kdDebug(5003) << "KNodeView::~KNodeView() : Net deleted" << endl; delete a_rtManager; kdDebug(5003) << "KNodeView::~KNodeView() : Article Manager deleted" << endl; delete a_rtFactory; kdDebug(5003) << "KNodeView::~KNodeView() : Article Factory deleted" << endl; delete g_rpManager; kdDebug(5003) << "KNodeView::~KNodeView() : Group Manager deleted" << endl; delete f_olManager; kdDebug(5003) << "KNodeView::~KNodeView() : Folder Manager deleted" << endl; delete f_ilManager; kdDebug(5003) << "KNodeView::~KNodeView() : Filter Manager deleted" << endl; delete a_ccManager; kdDebug(5003) << "KNodeView::~KNodeView() : Account Manager deleted" << endl; delete c_fgManager; kdDebug(5003) << "KNodeView::~KNodeView() : Config deleted" << endl; } void KNodeView::readOptions() { KConfig *conf=KGlobal::config(); conf->setGroup("APPEARANCE"); QValueList lst = conf->readIntListEntry("Vert_SepPos"); if (lst.count()!=2) lst << 266 << 487; if (l_ongView) setSizes(lst); else s_ecSplitter->setSizes(lst); lst = conf->readIntListEntry("Horz_SepPos"); if (lst.count()!=2) lst << 153 << 234; if (l_ongView) s_ecSplitter->setSizes(lst); else setSizes(lst); lst = conf->readIntListEntry("Hdrs_Size"); - if (lst.count()==7) { + if (lst.count()==8) { QValueList::Iterator it = lst.begin(); QHeader *h=c_olView->header(); for (int i=0; i<3; i++) { h->resizeSection(i,(*it)); ++it; } h=h_drView->header(); - for (int i=0; i<4; i++) { + for (int i=0; i<5; i++) { h->resizeSection(i,(*it)); ++it; } } lst = conf->readIntListEntry("Hdr_Order"); - if (lst.count()==7) { + if (lst.count()==8) { QValueList::Iterator it = lst.begin(); QHeader *h=c_olView->header(); for (int i=0; i<3; i++) { h->moveSection(i,(*it)); ++it; } h=h_drView->header(); - for (int i=0; i<4; i++) { + for (int i=0; i<5; i++) { h->moveSection(i,(*it)); ++it; } } int sortCol=conf->readNumEntry("sortCol",3); bool sortAsc=conf->readBoolEntry("sortAscending", false); h_drView->setColAsc(sortCol, sortAsc); h_drView->setSorting(sortCol, sortAsc); a_ctArtSortHeaders->setCurrentItem(sortCol); sortCol = conf->readNumEntry("account_sortCol", 0); sortAsc = conf->readBoolEntry("account_sortAscending", true); c_olView->setColAsc(sortCol, sortAsc); c_olView->setSorting(sortCol, sortAsc); a_rtManager->setShowThreads( conf->readBoolEntry("showThreads", true) ); a_ctArtToggleShowThreads->setChecked( a_rtManager->showThreads() ); a_rtView->setShowFullHdrs( conf->readBoolEntry("fullHdrs", false) ); } void KNodeView::saveOptions() { KConfig *conf=KGlobal::config(); conf->setGroup("APPEARANCE"); if (l_ongView) { conf->writeEntry("Vert_SepPos",sizes()); conf->writeEntry("Horz_SepPos",s_ecSplitter->sizes()); } else { conf->writeEntry("Vert_SepPos",s_ecSplitter->sizes()); conf->writeEntry("Horz_SepPos",sizes()); } // store section sizes QValueList lst; QHeader *h=c_olView->header(); for (int i=0; i<3; i++) lst << h->sectionSize(i); h=h_drView->header(); - for (int i=0; i<4; i++) + for (int i=0; i<5; i++) lst << h->sectionSize(i); conf->writeEntry("Hdrs_Size", lst); // store section order lst.clear(); h=c_olView->header(); for (int i=0; i<3; i++) lst << h->mapToIndex(i); h=h_drView->header(); - for (int i=0; i<4; i++) + for (int i=0; i<5; i++) lst << h->mapToIndex(i); conf->writeEntry("Hdr_Order", lst); // store sorting setup conf->writeEntry("sortCol", h_drView->sortColumn()); conf->writeEntry("sortAscending", h_drView->ascending()); conf->writeEntry("account_sortCol", c_olView->sortColumn()); conf->writeEntry("account_sortAscending", c_olView->ascending()); conf->writeEntry("showThreads", a_rtManager->showThreads()); conf->writeEntry("fullHdrs", a_rtView->showFullHdrs()); } bool KNodeView::cleanup() { if(!a_rtFactory->closeComposeWindows()) return false; //expire & compact KNConfig::Cleanup *conf=c_fgManager->cleanup(); KNCleanUp *cup=0; if(conf->expireToday()) { cup=new KNCleanUp(conf); g_rpManager->expireAll(cup); cup->start(); conf->setLastExpireDate(); } if(conf->compactToday()) { if(!cup) cup=new KNCleanUp(conf); else cup->reset(); f_olManager->compactAll(cup); cup->start(); conf->setLastCompactDate(); } if(cup) delete cup; return true; } // switch between long & short group list, update fonts and colors void KNodeView::configChanged() { KNConfig::Appearance *app=c_fgManager->appearance(); if(l_ongView != app->longGroupList()) { l_ongView = app->longGroupList(); QValueList size1 = sizes(); QValueList size2 = s_ecSplitter->sizes(); if(l_ongView) { setOrientation(Qt::Horizontal); s_ecSplitter->setOrientation(Qt::Vertical); a_rtFocus->reparent(s_ecSplitter,0,QPoint(0,0),true); c_olFocus->reparent(this,0,QPoint(0,0),true); moveToFirst(c_olFocus); moveToLast(s_ecSplitter); setResizeMode(c_olFocus, QSplitter::KeepSize); setResizeMode(s_ecSplitter, QSplitter::Stretch); s_ecSplitter->moveToFirst(h_drFocus); s_ecSplitter->moveToLast(a_rtFocus); s_ecSplitter->setResizeMode(h_drFocus, QSplitter::KeepSize); s_ecSplitter->setResizeMode(a_rtFocus, QSplitter::Stretch); } else { setOrientation(Qt::Vertical); s_ecSplitter->setOrientation(Qt::Horizontal); a_rtFocus->reparent(this,0,QPoint(0,0),true); c_olFocus->reparent(s_ecSplitter,0,QPoint(0,0),true); moveToFirst(s_ecSplitter); moveToLast(a_rtFocus); setResizeMode(s_ecSplitter, QSplitter::KeepSize); setResizeMode(a_rtFocus, QSplitter::Stretch); s_ecSplitter->moveToFirst(c_olFocus); s_ecSplitter->moveToLast(h_drFocus); s_ecSplitter->setResizeMode(c_olFocus, QSplitter::KeepSize); s_ecSplitter->setResizeMode(h_drFocus, QSplitter::Stretch); } setSizes(size2); s_ecSplitter->setSizes(size1); } c_olView->setFont(app->groupListFont()); + KNHdrViewItem::clearFontCache(); h_drView->setFont(app->articleListFont()); QPalette p = palette(); p.setColor(QColorGroup::Base, app->backgroundColor()); c_olView->setPalette(p); h_drView->setPalette(p); + if (knGlobals.cfgManager->readNewsGeneral()->showScore()) { + if (!h_drView->header()->isResizeEnabled(2)) { + h_drView->header()->setResizeEnabled(true,2); + h_drView->header()->resizeSection(2,42); + } + } else { + h_drView->header()->resizeSection(2,0); + h_drView->header()->setResizeEnabled(false,2); + } + if (knGlobals.cfgManager->readNewsGeneral()->showLines()) { + if (!h_drView->header()->isResizeEnabled(3)) { + h_drView->header()->setResizeEnabled(true,3); + h_drView->header()->resizeSection(3,42); + } + } else { + h_drView->header()->resizeSection(3,0); + h_drView->header()->setResizeEnabled(false,3); + } } void KNodeView::initActions() { //navigation a_ctNavNextArt = new KAction(i18n("&Next article"), "next", Key_N , this, SLOT(slotNavNextArt()), a_ctions, "go_nextArticle"); a_ctNavPrevArt = new KAction(i18n("&Previous article"), "previous", Key_B , this, SLOT(slotNavPrevArt()), a_ctions, "go_prevArticle"); a_ctNavNextUnreadArt = new KAction(i18n("Next unread &article"), "1rightarrow", ALT+Key_Space , this, SLOT(slotNavNextUnreadArt()), a_ctions, "go_nextUnreadArticle"); a_ctNavNextUnreadThread = new KAction(i18n("Next unread &thread"),"2rightarrow", CTRL+Key_Space , this, SLOT(slotNavNextUnreadThread()), a_ctions, "go_nextUnreadThread"); a_ctNavNextGroup = new KAction(i18n("Ne&xt group"), "down", Key_Plus , this, SLOT(slotNavNextGroup()), a_ctions, "go_nextGroup"); a_ctNavPrevGroup = new KAction(i18n("Pre&vious group"), "up", Key_Minus , this, SLOT(slotNavPrevGroup()), a_ctions, "go_prevGroup"); a_ctNavReadThrough = new KAction(i18n("Read &through articles"), Key_Space , this, SLOT(slotNavReadThrough()), a_ctions, "go_readThrough"); //collection-view - accounts a_ctAccProperties = new KAction(i18n("&Properties..."), 0, this, SLOT(slotAccProperties()), a_ctions, "account_properties"); a_ctAccSubscribe = new KAction(i18n("&Subscribe to Newsgroups..."),"news_subscribe", 0, this, SLOT(slotAccSubscribe()), a_ctions, "account_subscribe"); a_ctAccGetNewHdrs = new KAction(i18n("&Get New Articles"), "mail_get", 0, this, SLOT(slotAccGetNewHdrs()), a_ctions, "account_dnlHeaders"); a_ctAccDelete = new KAction(i18n("&Delete"), 0, this, SLOT(slotAccDelete()), a_ctions, "account_delete"); a_ctAccPostNewArticle = new KAction(i18n("&Post to Newsgroup..."), "filenew", Key_P , this, SLOT(slotAccPostNewArticle()), a_ctions, "article_postNew"); //collection-view - groups a_ctGrpProperties = new KAction(i18n("&Properties..."), 0, this, SLOT(slotGrpProperties()), a_ctions, "group_properties"); a_ctGrpGetNewHdrs = new KAction(i18n("&Get New Articles"), "mail_get" , 0, this, SLOT(slotGrpGetNewHdrs()), a_ctions, "group_dnlHeaders"); a_ctGrpExpire = new KAction(i18n("E&xpire Now"), "wizard", 0, this, SLOT(slotGrpExpire()), a_ctions, "group_expire"); a_ctGrpResort = new KAction(i18n("Res&ort"), 0, this, SLOT(slotGrpResort()), a_ctions, "group_resort"); a_ctGrpUnsubscribe = new KAction(i18n("&Unsubscribe"), "news_unsubscribe", 0, this, SLOT(slotGrpUnsubscribe()), a_ctions, "group_unsubscribe"); a_ctGrpSetAllRead = new KAction(i18n("Mark all as &read"), "goto", 0, this, SLOT(slotGrpSetAllRead()), a_ctions, "group_allRead"); a_ctGrpSetAllUnread = new KAction(i18n("Mark all as u&nread"), 0, this, SLOT(slotGrpSetAllUnread()), a_ctions, "group_allUnread"); //collection-view - folder a_ctFolCompact = new KAction(i18n("&Compact Folder"), "wizard", 0, this, SLOT(slotFolCompact()), a_ctions, "folder_compact"); a_ctFolEmpty = new KAction(i18n("&Empty Folder"), 0, this, SLOT(slotFolEmpty()), a_ctions, "folder_empty"); a_ctFolProperties = 0; //header-view - list-handling a_ctArtSortHeaders = new KSelectAction(i18n("S&ort"), 0, a_ctions, "view_Sort"); QStringList items; items += i18n("By &Subject"); items += i18n("By S&ender"); items += i18n("By S&core"); + items += i18n("By &Lines"); items += i18n("By &Date"); a_ctArtSortHeaders->setItems(items); connect(a_ctArtSortHeaders, SIGNAL(activated(int)), this, SLOT(slotArtSortHeaders(int))); a_ctArtFilter = new KNFilterSelectAction(i18n("&Filter"), "filter", a_ctions, "view_Filter"); a_ctArtSearch = new KAction(i18n("&Search Articles..."),"find" , Key_F4 , this, SLOT(slotArtSearch()), a_ctions, "article_search"); a_ctArtRefreshList = new KAction(i18n("&Refresh List"),"reload", KStdAccel::key(KStdAccel::Reload), this, SLOT(slotArtRefreshList()), a_ctions, "view_Refresh"); a_ctArtCollapseAll = new KAction(i18n("&Collapse all threads"), 0 , this, SLOT(slotArtCollapseAll()), a_ctions, "view_CollapseAll"); a_ctArtExpandAll = new KAction(i18n("E&xpand all threads"), 0 , this, SLOT(slotArtExpandAll()), a_ctions, "view_ExpandAll"); a_ctArtToggleThread = new KAction(i18n("&Toggle Subthread"), Key_T, this, SLOT(slotArtToggleThread()), a_ctions, "thread_toggle"); a_ctArtToggleShowThreads = new KToggleAction(i18n("Show T&hreads"), 0 , this, SLOT(slotArtToggleShowThreads()), a_ctions, "view_showThreads"); //header-view - remote articles a_ctArtSetArtRead = new KAction(i18n("Mark as &read"), Key_D , this, SLOT(slotArtSetArtRead()), a_ctions, "article_read"); a_ctArtSetArtUnread = new KAction(i18n("Mar&k as unread"), Key_U , this, SLOT(slotArtSetArtUnread()), a_ctions, "article_unread"); a_ctArtSetThreadRead = new KAction(i18n("Mark thread as r&ead"), CTRL+Key_D , this, SLOT(slotArtSetThreadRead()), a_ctions, "thread_read"); a_ctArtSetThreadUnread = new KAction(i18n("Mark thread as u&nread"), CTRL+Key_U , this, SLOT(slotArtSetThreadUnread()), a_ctions, "thread_unread"); a_ctSetArtScore = new KAction(i18n("Set Sc&ore"), "rotate", Key_S , this, SLOT(slotArtSetArtScore()), a_ctions, "article_setScore"); a_ctArtSetThreadScore = new KAction(i18n("Set Score of &thread"), "rotate", CTRL+Key_S , this, SLOT(slotArtSetThreadScore()), a_ctions, "thread_setScore"); a_ctArtToggleIgnored = new KAction(i18n("&Ignore"), "bottom", Key_I , this, SLOT(slotArtToggleIgnored()), a_ctions, "thread_ignore"); a_ctArtToggleWatched = new KAction(i18n("&Watch"), "top", Key_W , this, SLOT(slotArtToggleWatched()), a_ctions, "thread_watch"); a_ctArtOpenNewWindow = new KAction(i18n("Open in own &window"), "viewmag+", Key_O , this, SLOT(slotArtOpenNewWindow()), a_ctions, "article_ownWindow"); //header-view local articles a_ctArtSendOutbox = new KAction(i18n("Sen&d pending messages"), "mail_send", 0, this, SLOT(slotArtSendOutbox()), a_ctions, "net_sendPending"); a_ctArtDelete = new KAction(i18n("&Delete"), "editdelete", Key_Delete, this, SLOT(slotArtDelete()), a_ctions, "article_delete"); a_ctArtSendNow = new KAction(i18n("Send &now"),"mail_send", 0 , this, SLOT(slotArtSendNow()), a_ctions, "article_sendNow"); a_ctArtEdit = new KAction(i18n("edit article","&Edit..."), "signature", Key_E , this, SLOT(slotArtEdit()), a_ctions, "article_edit"); //network a_ctNetCancel = new KAction(i18n("Stop &Network"),"stop",0, this, SLOT(slotNetCancel()), a_ctions, "net_stop"); a_ctNetCancel->setEnabled(false); } // called after createGUI() void KNodeView::initPopups(KNMainWindow *w) { a_ccPopup = static_cast(w->factory()->container("account_popup", w)); if (!a_ccPopup) a_ccPopup = new QPopupMenu(w); g_roupPopup = static_cast(w->factory()->container("group_popup", w)); if (!g_roupPopup) g_roupPopup = new QPopupMenu(w); f_olderPopup = static_cast(w->factory()->container("folder_popup", w)); if (!f_olderPopup) f_olderPopup = new QPopupMenu(w); r_emotePopup = static_cast(w->factory()->container("remote_popup", w)); if (!r_emotePopup) r_emotePopup = new QPopupMenu(w); l_ocalPopup = static_cast(w->factory()->container("local_popup", w)); if (!l_ocalPopup) l_ocalPopup = new QPopupMenu(w); QPopupMenu *pop = static_cast(w->factory()->container("body_popup", w)); if (!pop) pop = new QPopupMenu(w); a_rtView->setBodyPopup(pop); } void KNodeView::paletteChange ( const QPalette & ) { knGlobals.cfgManager->appearance()->updateHexcodes(); KNArticleWidget::configChanged(); configChanged(); } void KNodeView::fontChange ( const QFont & ) { knGlobals.artFactory->configChanged(); KNArticleWidget::configChanged(); configChanged(); } void KNodeView::slotArticleSelected(QListViewItem *i) { kdDebug(5003) << "KNodeView::slotArticleSelected(QListViewItem *i)" << endl; if(b_lockui) return; s_electedArticle=0; if(i) s_electedArticle=(static_cast(i))->art; a_rtView->setArticle(s_electedArticle); //actions bool enabled; enabled=( s_electedArticle && s_electedArticle->type()==KNMimeBase::ATremote ); if(a_ctArtSetArtRead->isEnabled() != enabled) { a_ctArtSetArtRead->setEnabled(enabled); a_ctArtSetArtUnread->setEnabled(enabled); a_ctArtSetThreadRead->setEnabled(enabled); a_ctArtSetThreadUnread->setEnabled(enabled); a_ctSetArtScore->setEnabled(enabled); a_ctArtSetThreadScore->setEnabled(enabled); a_ctArtToggleIgnored->setEnabled(enabled); a_ctArtToggleWatched->setEnabled(enabled); } a_ctArtOpenNewWindow->setEnabled( s_electedArticle && (f_olManager->currentFolder()!=f_olManager->outbox()) && (f_olManager->currentFolder()!=f_olManager->drafts())); enabled=( s_electedArticle && s_electedArticle->type()==KNMimeBase::ATlocal ); a_ctArtDelete->setEnabled(enabled); a_ctArtSendNow->setEnabled(enabled && (f_olManager->currentFolder()==f_olManager->outbox())); a_ctArtEdit->setEnabled(enabled && ((f_olManager->currentFolder()==f_olManager->outbox())|| (f_olManager->currentFolder()==f_olManager->drafts()))); } void KNodeView::slotArticleDoubleClicked(QListViewItem *it) { if(!it) return; KNArticle *art=(static_cast(it))->art; if ((art->type()==KNMimeBase::ATlocal) && ((f_olManager->currentFolder()==f_olManager->outbox())|| (f_olManager->currentFolder()==f_olManager->drafts()))) { a_rtFactory->edit( static_cast(art) ); } else { KNArticleWindow *w=new KNArticleWindow(art); w->show(); } } void KNodeView::slotCollectionSelected(QListViewItem *i) { kdDebug(5003) << "KNodeView::slotCollectionSelected(QListViewItem *i)" << endl; if(b_lockui) return; KNCollection *c=0; s_electedAccount=0; s_electedGroup=0; s_electedFolder=0; QString caption; h_drView->clear(); slotArticleSelected(0); if(i) { c=(static_cast(i))->coll; switch(c->type()) { case KNCollection::CTnntpAccount : s_electedAccount=static_cast(c); if(!i->isOpen()) i->setOpen(true); knGlobals.top->setCaption(s_electedAccount->name()); break; case KNCollection::CTgroup : if (!(h_drView->hasFocus())&&!(a_rtView->hasFocus())) h_drView->setFocus(); s_electedGroup=static_cast(c); s_electedAccount=s_electedGroup->account(); caption = s_electedGroup->name(); if (s_electedGroup->status()==KNGroup::moderated) caption += i18n(" (moderated)"); knGlobals.top->setCaption(caption); break; case KNCollection::CTfolder : if (!(h_drView->hasFocus())&&!(a_rtView->hasFocus())) h_drView->setFocus(); s_electedFolder=static_cast(c); knGlobals.top->setCaption(s_electedFolder->name()); break; default: break; } } a_ccManager->setCurrentAccount(s_electedAccount); g_rpManager->setCurrentGroup(s_electedGroup); f_olManager->setCurrentFolder(s_electedFolder); //actions bool enabled; enabled=(s_electedGroup) || (s_electedFolder); if(a_ctNavNextArt->isEnabled() != enabled) { a_ctNavNextArt->setEnabled(enabled); a_ctNavPrevArt->setEnabled(enabled); } enabled=( s_electedGroup!=0 ); if(a_ctNavNextUnreadArt->isEnabled() != enabled) { a_ctNavNextUnreadArt->setEnabled(enabled); a_ctNavNextUnreadThread->setEnabled(enabled); a_ctNavReadThrough->setEnabled(enabled); } enabled=( s_electedAccount!=0 ); if(a_ctAccProperties->isEnabled() != enabled) { a_ctAccProperties->setEnabled(enabled); a_ctAccSubscribe->setEnabled(enabled); a_ctAccGetNewHdrs->setEnabled(enabled); a_ctAccDelete->setEnabled(enabled); a_ctAccPostNewArticle->setEnabled(enabled); } enabled=( s_electedGroup!=0 ); if(a_ctGrpProperties->isEnabled() != enabled) { a_ctGrpProperties->setEnabled(enabled); a_ctGrpGetNewHdrs->setEnabled(enabled); a_ctGrpExpire->setEnabled(enabled); a_ctGrpResort->setEnabled(enabled); a_ctGrpUnsubscribe->setEnabled(enabled); a_ctGrpSetAllRead->setEnabled(enabled); a_ctGrpSetAllUnread->setEnabled(enabled); - a_ctArtSortHeaders->setEnabled(enabled); a_ctArtFilter->setEnabled(enabled); a_ctArtSearch->setEnabled(enabled); a_ctArtRefreshList->setEnabled(enabled); a_ctArtCollapseAll->setEnabled(enabled); a_ctArtExpandAll->setEnabled(enabled); - a_ctArtToggleShowThreads->setEnabled(enabled); + a_ctArtToggleShowThreads->setEnabled(enabled); } enabled=( s_electedFolder!=0 ); if(a_ctFolCompact->isEnabled() != enabled) { a_ctFolCompact->setEnabled(enabled); a_ctFolEmpty->setEnabled(enabled); //a_ctFolProperties->setEnabled( (s_electedFolder) ); } } void KNodeView::slotArticleRMB(QListViewItem *i, const QPoint &p, int) { if(b_lockui) return; if(i) { if( (static_cast(i))->art->type()==KNMimeBase::ATremote) r_emotePopup->popup(p); else l_ocalPopup->popup(p); } } void KNodeView::slotCollectionRMB(QListViewItem *i, const QPoint &p, int) { if(b_lockui) return; if(i) { if( (static_cast(i))->coll->type()==KNCollection::CTgroup) g_roupPopup->popup(p); else if ((static_cast(i))->coll->type()==KNCollection::CTfolder) f_olderPopup->popup(p); else a_ccPopup->popup(p); } } void KNodeView::slotHdrViewSortingChanged(int i) { a_ctArtSortHeaders->setCurrentItem(i); } void KNodeView::slotNetworkActive(bool b) { a_ctNetCancel->setEnabled(b); } //------------------------------ -------------------------------- void KNodeView::slotNavNextArt() { kdDebug(5003) << "KNodeView::slotNavNextArt()" << endl; QListViewItem *it=h_drView->currentItem(); if(it) it=it->itemBelow(); else it=h_drView->firstChild(); if(it) { h_drView->setActive(it, true); h_drView->setCurrentItem(it); h_drView->ensureItemVisible(it); } } void KNodeView::slotNavPrevArt() { kdDebug(5003) << "KNodeView::slotNavPrevArt()" << endl; QListViewItem *it=h_drView->currentItem(); if(it) it=it->itemAbove(); else it=h_drView->firstChild(); if(it) { h_drView->setActive(it, true); h_drView->setCurrentItem(it); h_drView->ensureItemVisible(it); } } void KNodeView::slotNavNextUnreadArt() { kdDebug(5003) << "KNodeView::slotNavNextUnreadArt()" << endl; if(!s_electedGroup) return; KNHdrViewItem *next, *current; KNRemoteArticle *art; current=static_cast(h_drView->currentItem()); if(!current) current=static_cast(h_drView->firstChild()); if(!current) { // no articles in the current group switch to next.... slotNavNextGroup(); return; } art=static_cast(current->art); if ((!current->isActive())&&(!art->isRead())) // take current article, if unread & not selected next=current; else { if(current->isExpandable() && !current->isOpen()) h_drView->setOpen(current, true); next=static_cast(current->itemBelow()); } while(next) { art=static_cast(next->art); if(!art->isRead()) break; else { if(next->isExpandable() && !next->isOpen()) h_drView->setOpen(next, true); next=static_cast(next->itemBelow()); } } if(next) { h_drView->setActive(next, true); h_drView->setCurrentItem(next); h_drView->ensureItemVisible(next); } else slotNavNextGroup(); } void KNodeView::slotNavNextUnreadThread() { kdDebug(5003) << "KNodeView::slotNavNextUnreadThread()" << endl; KNHdrViewItem *next, *current; KNRemoteArticle *art; if(!s_electedGroup) return; current=static_cast(h_drView->currentItem()); if(!current) current=static_cast(h_drView->firstChild()); if(!current) { // no articles in the current group switch to next.... slotNavNextGroup(); return; } art=static_cast(current->art); if((current->depth()==0)&&((!current->isActive())&&(!art->isRead() || art->hasUnreadFollowUps()))) next=current; // take current article, if unread & not selected else next=static_cast(current->itemBelow()); while(next) { art=static_cast(next->art); if(next->depth()==0) { if(!art->isRead() || art->hasUnreadFollowUps()) break; } next=static_cast(next->itemBelow()); } if(next) { h_drView->setCurrentItem(next); if(art->isRead()) slotNavNextUnreadArt(); else { h_drView->setActive(next, true); h_drView->setCurrentItem(next); h_drView->ensureItemVisible(next); } } else slotNavNextGroup(); } void KNodeView::slotNavNextGroup() { kdDebug(5003) << "KNodeView::slotNavNextGroup()" << endl; KNCollectionViewItem *current=static_cast(c_olView->currentItem()); KNCollectionViewItem *next=0; if(!current) current=(KNCollectionViewItem*)c_olView->firstChild(); if(!current) return; next=current; while(next) { if(!next->isActive()) break; if(next->childCount()>0 && !next->isOpen()) { next->setOpen(true); knGlobals.top->secureProcessEvents(); next=static_cast(next->firstChild()); } else next=static_cast(next->itemBelow()); } if(next) { c_olView->setActive(next, true); c_olView->setCurrentItem(next); c_olView->ensureItemVisible(next); } } void KNodeView::slotNavPrevGroup() { kdDebug(5003) << "KNodeView::slotNavPrevGroup()" << endl; KNCollectionViewItem *current=static_cast(c_olView->currentItem()); KNCollectionViewItem *prev; if(!current) current=static_cast(c_olView->firstChild()); if(!current) return; prev=current; while(prev) { if(!prev->isActive()) break; prev=static_cast(prev->itemAbove()); } if(prev) { c_olView->setActive(prev, true); c_olView->setCurrentItem(prev); c_olView->ensureItemVisible(prev); } } void KNodeView::slotNavReadThrough() { kdDebug(5003) << "KNodeView::slotNavReadThrough()" << endl; if (a_rtView->scrollingDownPossible()) a_rtView->scrollDown(); else if(s_electedGroup != 0) slotNavNextUnreadArt(); } void KNodeView::slotAccProperties() { kdDebug(5003) << "KNodeView::slotAccProperties()" << endl; if(s_electedAccount) a_ccManager->editProperties(s_electedAccount); } void KNodeView::slotAccSubscribe() { kdDebug(5003) << "KNodeView::slotAccSubscribe()" << endl; if(s_electedAccount) g_rpManager->showGroupDialog(s_electedAccount); } void KNodeView::slotAccGetNewHdrs() { kdDebug(5003) << "KNodeView::slotAccGetNewHdrs()" << endl; if(s_electedAccount) g_rpManager->checkAll(s_electedAccount); } void KNodeView::slotAccDelete() { kdDebug(5003) << "KNodeView::slotAccDelete()" << endl; if(s_electedAccount) a_ccManager->removeAccount(s_electedAccount); } void KNodeView::slotAccPostNewArticle() { kdDebug(5003) << "KNodeView::slotAccPostNewArticle()" << endl; if(s_electedGroup) a_rtFactory->createPosting(s_electedGroup); else if(s_electedAccount) a_rtFactory->createPosting(s_electedAccount); } void KNodeView::slotGrpProperties() { kdDebug(5003) << "slotGrpProperties()" << endl; if(s_electedGroup) g_rpManager->showGroupProperties(s_electedGroup); } void KNodeView::slotGrpGetNewHdrs() { kdDebug(5003) << "KNodeView::slotGrpGetNewHdrs()" << endl; if(s_electedGroup) g_rpManager->checkGroupForNewHeaders(s_electedGroup); } void KNodeView::slotGrpExpire() { kdDebug(5003) << "KNodeView::slotGrpExpire()" << endl; if(s_electedGroup) g_rpManager->expireGroupNow(s_electedGroup); } void KNodeView::slotGrpResort() { kdDebug(5003) << "KNodeView::slotGrpResort()" << endl; if(s_electedGroup) g_rpManager->resortGroup(s_electedGroup); } void KNodeView::slotGrpUnsubscribe() { kdDebug(5003) << "KNodeView::slotGrpUnsubscribe()" << endl; if(s_electedGroup) if(KMessageBox::Yes==KMessageBox::questionYesNo(knGlobals.topWidget, i18n("Do you really want to unsubscribe from %1?").arg(s_electedGroup->groupname()))) g_rpManager->unsubscribeGroup(s_electedGroup); } void KNodeView::slotGrpSetAllRead() { kdDebug(5003) << "KNodeView::slotGrpSetAllRead()" << endl; a_rtManager->setAllRead(true); } void KNodeView::slotGrpSetAllUnread() { kdDebug(5003) << "KNodeView::slotGrpSetAllUnread()" << endl; a_rtManager->setAllRead(false); } void KNodeView::slotFolCompact() { kdDebug(5003) << "KNodeView::slotFolCompact()" << endl; if(s_electedFolder) f_olManager->compactFolder(s_electedFolder); } void KNodeView::slotFolEmpty() { kdDebug(5003) << "KNodeView::slotFolEmpty()" << endl; if(s_electedFolder) { if(s_electedFolder->lockedArticles()>0) { KMessageBox::sorry(knGlobals.topWidget, i18n("This Folder cannot be emptied at the moment\nbecause some of it's articles are currently in use.") ); return; } if( KMessageBox::Yes == KMessageBox::questionYesNo( knGlobals.topWidget, i18n("Do you really want to empty this folder?")) ) s_electedFolder->deleteAll(); } } void KNodeView::slotFolProperties() { kdDebug(5003) << "KNodeView::slotFolProperties()" << endl; } void KNodeView::slotArtSortHeaders(int i) { kdDebug(5003) << "KNodeView::slotArtSortHeaders(int i)" << endl; h_drView->slotSortList(i); } void KNodeView::slotArtSearch() { kdDebug(5003) << "KNodeView::slotArtSearch()" << endl; a_rtManager->search(); } void KNodeView::slotArtRefreshList() { kdDebug(5003) << "KNodeView::slotArtRefreshList()" << endl; a_rtManager->showHdrs(true); } void KNodeView::slotArtCollapseAll() { kdDebug(5003) << "KNodeView::slotArtCollapseAll()" << endl; a_rtManager->setAllThreadsOpen(false); } void KNodeView::slotArtExpandAll() { kdDebug(5003) << "KNodeView::slotArtExpandAll()" << endl; a_rtManager->setAllThreadsOpen(true); } void KNodeView::slotArtToggleThread() { kdDebug(5003) << "KNodeView::slotArtToggleThread()" << endl; if(s_electedArticle && s_electedArticle->listItem()->isExpandable()) { bool o=!(s_electedArticle->listItem()->isOpen()); s_electedArticle->listItem()->setOpen(o); } } void KNodeView::slotArtToggleShowThreads() { kdDebug(5003) << "KNodeView::slotArtToggleShowThreads()" << endl; if(s_electedGroup) { a_rtManager->toggleShowThreads(); } } void KNodeView::slotArtSetArtRead() { kdDebug(5003) << "KNodeView::slotArtSetArtRead()" << endl; if(!s_electedGroup) return; KNRemoteArticle::List l; for(QListViewItem *i=h_drView->firstChild(); i; i=i->itemBelow()) if(i->isSelected()) l.append( static_cast ((static_cast(i))->art) ); a_rtManager->setRead(&l, true); } void KNodeView::slotArtSetArtUnread() { kdDebug(5003) << "KNodeView::slotArtSetArtUnread()" << endl; if(!s_electedGroup) return; KNRemoteArticle::List l; for(QListViewItem *i=h_drView->firstChild(); i; i=i->itemBelow()) if(i->isSelected()) l.append( static_cast ((static_cast(i))->art) ); a_rtManager->setRead(&l, false); } void KNodeView::slotArtSetThreadRead() { kdDebug(5003) << "slotArtSetThreadRead()" << endl; if( !s_electedArticle || !s_electedGroup ) return; KNRemoteArticle::List l; (static_cast(s_electedArticle))->thread(&l); a_rtManager->setRead(&l, true); } void KNodeView::slotArtSetThreadUnread() { kdDebug(5003) << "KNodeView::slotArtSetThreadUnread()" << endl; if( !s_electedArticle || !s_electedGroup ) return; KNRemoteArticle::List l; (static_cast(s_electedArticle))->thread(&l); a_rtManager->setRead( &l, false); } void KNodeView::slotArtSetArtScore() { kdDebug(5003) << "KNodeView::slotArtSetArtScore()" << endl; KNRemoteArticle::List l; for(QListViewItem *i=h_drView->firstChild(); i; i=i->itemBelow()) if(i->isSelected()) l.append( static_cast ((static_cast(i))->art) ); if(l.isEmpty()) return; int score=l.first()->score(); KNScoreDialog *sd=new KNScoreDialog(score, knGlobals.topWidget); if(sd->exec()) { score=sd->score(); delete sd; a_rtManager->setScore(&l, score); } else delete sd; } void KNodeView::slotArtSetThreadScore() { kdDebug(5003) << "KNodeView::slotArtSetThreadScore()" << endl; if( !s_electedArticle || !s_electedGroup ) return; KNRemoteArticle::List l; (static_cast(s_electedArticle))->thread(&l); int score=l.first()->score(); KNScoreDialog *sd= new KNScoreDialog(score, knGlobals.topWidget); if(sd->exec()) { score=sd->score(); delete sd; a_rtManager->setScore(&l, score); } else delete sd; } void KNodeView::slotArtToggleIgnored() { kdDebug(5003) << "KNodeView::slotArtToggleIgnored()" << endl; if( !s_electedArticle || !s_electedGroup ) return; KNRemoteArticle::List l; (static_cast(s_electedArticle))->thread(&l); a_rtManager->toggleIgnored(&l); } void KNodeView::slotArtToggleWatched() { kdDebug(5003) << "KNodeView::slotArtToggleWatched()" << endl; if( !s_electedArticle || !s_electedGroup ) return; KNRemoteArticle::List l; (static_cast(s_electedArticle))->thread(&l); a_rtManager->toggleWatched(&l); } void KNodeView::slotArtOpenNewWindow() { kdDebug(5003) << "KNodeView::slotArtOpenNewWindow()" << endl; if(s_electedArticle) { KNArticleWindow *win=new KNArticleWindow(s_electedArticle); win->show(); } } void KNodeView::slotArtSendOutbox() { kdDebug(5003) << "KNodeView::slotArtSendOutbox()" << endl; a_rtFactory->sendOutbox(); } void KNodeView::slotArtDelete() { kdDebug(5003) << "KNodeView::slotArtDelete()" << endl; KNLocalArticle::List lst; for(QListViewItem *i=h_drView->firstChild(); i; i=i->itemBelow()) if(i->isSelected()) lst.append( static_cast ((static_cast(i))->art) ); if(!lst.isEmpty()) a_rtFactory->deleteArticles(&lst); if(h_drView->currentItem()) h_drView->setActive(h_drView->currentItem(),true); } void KNodeView::slotArtSendNow() { kdDebug(5003) << "KNodeView::slotArtSendNow()" << endl; KNLocalArticle::List lst; for(QListViewItem *i=h_drView->firstChild(); i; i=i->itemBelow()) if(i->isSelected()) lst.append( static_cast ((static_cast(i))->art) ); if(!lst.isEmpty()) a_rtFactory->sendArticles(&lst, true); } void KNodeView::slotArtEdit() { kdDebug(5003) << "KNodeVew::slotArtEdit()" << endl; if (s_electedArticle && s_electedArticle->type()==KNMimeBase::ATlocal) a_rtFactory->edit(static_cast(s_electedArticle)); } void KNodeView::slotNetCancel() { kdDebug(5003) << "KNodeView::slotNetCancel()" << endl; n_etAccess->cancelAllJobs(); } //-------------------------------- ---------------------------------- //============================================================================== KNFilterSelectAction::KNFilterSelectAction( const QString& text, const QString& pix, QObject* parent, const char *name ) : KActionMenu(text,pix,parent,name), currentItem(-42) { popupMenu()->setCheckable(true); connect(popupMenu(),SIGNAL(activated(int)),this,SLOT(slotMenuActivated(int))); setDelayed(false); } KNFilterSelectAction::~KNFilterSelectAction() { } void KNFilterSelectAction::setCurrentItem(int id) { popupMenu()->setItemChecked(currentItem, false); popupMenu()->setItemChecked(id, true); currentItem = id; } void KNFilterSelectAction::slotMenuActivated(int id) { setCurrentItem(id); emit(activated(id)); } #include "knodeview.moc" diff --git a/knode/knpgpbase.cpp b/knode/knpgpbase.cpp index ef6ad7ae60..371e1386fa 100644 --- a/knode/knpgpbase.cpp +++ b/knode/knpgpbase.cpp @@ -1,1661 +1,1661 @@ /** KPGP: Pretty good privacy en-/decryption class * This code is under GPL V2.0 * * @author Lars Knoll * * GNUPG support * @author "J. Nick Koston" * * PGP6 and other enhancements * @author Andreas Gungl * * code borrowed and changed for knode * @author Mathias Waack */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "knpgpbase.h" #include "knpgp.h" KNPgpBase::KNPgpBase() { //readConfig(); status = OK; } KNPgpBase::~KNPgpBase() { } //void //KNPgpBase::readConfig() //{ //KConfig *config = KNPgp::getConfig(); //pgpUser = config->readEntry("user"); //flagEncryptToSelf = config->readBoolEntry("encryptToSelf"); //} //void //KNPgpBase::writeConfig(bool sync) //{ //KConfig *config = KNPgp::getConfig(); //config->writeEntry("user",pgpUser); //config->writeEntry("encryptToSelf",flagEncryptToSelf); //if(sync) //config->sync(); //} bool KNPgpBase::setMessage(const QString mess) { clear(); input = mess; if(input.find("-----BEGIN PGP") != -1) decrypt(); } QString KNPgpBase::message() const { // do we have a deciphered text? if(!output.isEmpty()) return output; // no, then return the original one //kdDebug() << "KNPgpBase: No output!" << endl; return input; } int KNPgpBase::run(const char *cmd, const char *passphrase) { /* the pipe ppass is used for to pass the password to * pgp. passing the password together with the normal input through * stdin doesn't seem to work as expected (at least for pgp5.0) */ char str[1024] = "\0"; int pin[2], pout[2], perr[2], ppass[2]; int len, status; FILE *pass; pid_t child_pid, rc; if(passphrase) { kdDebug(5003) << "piping password to pgp" << endl; pipe(ppass); pass = fdopen(ppass[1], "w"); fwrite(passphrase, sizeof(char), strlen(passphrase), pass); fwrite("\n", sizeof(char), 1, pass); fclose(pass); close(ppass[1]); // tell pgp which fd to use for the passphrase QCString tmp; tmp.sprintf("%d",ppass[0]); setenv("PGPPASSFD",tmp.data(),1); //printf("PGPPASSFD = %s\n",tmp.data()); //printf("pass = %s\n",passphrase); } else unsetenv("PGPPASSFD"); //printf("cmd = %s\n",cmd); //printf("input = %s\nlength = %d\n",input.data(), input.length()); info = ""; output = ""; KConfig *config = KGlobal::config(); config->setGroup("PRIVACY"); QString pgpexe = config->readEntry("progPath"); kdDebug(5003) << "running pgp as: " << pgpexe << " " << cmd << endl; pipe(pin); pipe(pout); pipe(perr); // there is a bug in pgp6 which creates a file called "stdin" and ask for // overwriting it in the following calls - not nice in batchmode char* tmpname = 0; if (!access("stdin", F_OK)) { tmpname = tempnam(".","stdin"); rename("stdin",tmpname); } QApplication::flushX(); if(!(child_pid = fork())) { /*We're the child.*/ close(pin[1]); dup2(pin[0], 0); close(pin[0]); close(pout[0]); dup2(pout[1], 1); close(pout[1]); close(perr[0]); dup2(perr[1], 2); close(perr[1]); execl("/bin/sh", "sh", "-c", pgpexe.latin1(), cmd, NULL); _exit(127); } /*Only get here if we're the parent.*/ close(pin[0]); close(pout[1]); close(perr[1]); if (!input.isEmpty()) { kdDebug(5003) << "writing to pgp: " << endl << input << endl; write(pin[1], input.latin1(), input.length()); write(pin[1], "\n", 1); // somtimes pgp ask to overwrite a file in batchmode:( } else { kdDebug(5003) << "no input for pgp" << endl; } close(pin[1]); #undef POLLING #ifdef POLLING kdDebug(5003) << "polling output from pgp" << endl; struct pollfd fds[2]; fds[0].fd = pout[0]; fds[0].events = POLLIN | POLLRDNORM; fds[1].fd = perr[0]; fds[1].events = POLLIN | POLLRDNORM; nfds_t nfds = 2; // set the fd's to nonblocking if (fds[0].fd >= 0) { int val = fcntl(fds[0].fd,F_GETFL,0); fcntl(fds[0].fd,F_SETFL, val | O_NONBLOCK); } if (fds[1].fd >= 0) { int val = fcntl(fds[1].fd,F_GETFL,0); fcntl(fds[1].fd,F_SETFL, val | O_NONBLOCK); } int rounds = 0; const int rounds_to_timeout = 4; while (rounds < rounds_to_timeout) { int res = poll(fds,nfds,100); kdDebug(5003) << "polling finished with result " << res << endl; if (res > 0) { kdDebug(5003) << "revents[0]: " << fds[0].revents << " revents[1]: " << fds[1].revents << endl; if (fds[0].revents & POLLRDNORM) { while ((len=read(pout[0],str,1023))>0) { str[len] ='\0'; output += str; } kdDebug(5003) << "output from pgp: " << endl << output << endl; } if (fds[1].revents & POLLRDNORM) { while ((len=read(perr[0],str,1023))>0) { str[len] ='\0'; info += str; } kdDebug(5003) << "output from pgp: " << endl << info << endl; } if ( (fds[0].revents & POLLHUP) && (fds[1].revents & POLLHUP) ) break; } if (res == 0) ++rounds; // timeout round } #else if (pout[0] >= 0) { while ((len=read(pout[0],str,1023))>0) { str[len] ='\0'; output += str; } kdDebug(5003) << "output from pgp: " << endl << output << endl; } if (perr[0] >= 0) { while ((len=read(perr[0],str,1023))>0) { str[len] ='\0'; info += str; } kdDebug(5003) << "output from pgp: " << endl << info << endl; } #endif unsetenv("PGPPASSFD"); if(passphrase) close(ppass[0]); //printf("output = %s\n",output.data()); //printf("info = %s\n",info.data()); // we don't want a zombie, do we? ;-) rc = waitpid(0/*child_pid*/, &status, 0); if (rc==-1) printf("waitpid: %s\n", strerror(errno)); // remove the temporary file from "stdin" rename(tmpname,"stdin"); return OK; } int KNPgpBase::runGpg(const char *cmd, const char *passphrase) { /* the pipe ppass is used for to pass the password to * pgp. passing the password together with the normal input through * stdin doesn't seem to work as expected (at least for pgp5.0) */ char str[1024] = "\0"; int pin[2], pout[2], perr[2], ppass[2]; int len, status; FILE *pass; pid_t child_pid, rc; //char gpgcmd[1024] = "\0"; if(passphrase) { pipe(ppass); pass = fdopen(ppass[1], "w"); fwrite(passphrase, sizeof(char), strlen(passphrase), pass); fwrite("\n", sizeof(char), 1, pass); fclose(pass); close(ppass[1]); //printf("pass = %s\n",passphrase); } //printf("cmd = %s\n",cmd); //printf("input = %s\nlength = %d\n",input.data(), input.length()); info = ""; output = ""; KConfig *config = KGlobal::config(); config->setGroup("PRIVACY"); QString pgpexe = config->readEntry("progPath"); kdDebug(5003) << "running gpg as: " << pgpexe << " " << cmd << endl; pipe(pin); pipe(pout); pipe(perr); //if(passphrase) { //snprintf(gpgcmd, 1023, "LANG=C; gpg --passphrase-fd %d %s",ppass[0],cmd); //} else { //snprintf(gpgcmd, 1023, "LANG=C; gpg %s",cmd); //} QString gpgcmd = pgpexe; //#warning FIXME: there has to be a better way to do this /* this is nasty nasty nasty (but it works) */ if(passphrase) { //snprintf(gpgcmd, 1023, "LANG=C; gpg --passphrase-fd %d %s",ppass[0],cmd); gpgcmd.prepend("LANG=C; "); gpgcmd.append(" --passphrase-fd "); gpgcmd.append( QString::number(ppass[0]) ); gpgcmd.append(" "); gpgcmd.append(cmd); } else { //snprintf(gpgcmd, 1023, "LANG=C; gpg %s",cmd); gpgcmd.prepend("LANG=C; "); gpgcmd.append(" "); gpgcmd.append(cmd); } kdDebug(5003) << "starting gpg: " << gpgcmd << endl; QApplication::flushX(); if(!(child_pid = fork())) { /*We're the child.*/ close(pin[1]); dup2(pin[0], 0); close(pin[0]); close(pout[0]); dup2(pout[1], 1); close(pout[1]); close(perr[0]); dup2(perr[1], 2); close(perr[1]); execl("/bin/sh", "sh", "-c", gpgcmd.latin1(), NULL); _exit(127); } /*Only get here if we're the parent.*/ close(pin[0]); close(pout[1]); close(perr[1]); if (!input.isEmpty()) { write(pin[1], input.latin1(), input.length()); kdDebug(5003) << "write to gpg: " << endl << input << endl; } else write(pin[1], "\n", 1); close(pin[1]); if (pout[0] >= 0) { while ((len=read(pout[0],str,1023))>0) { str[len] ='\0'; output += str; } close(pout[0]); kdDebug(5003) << "output from gpg: " << output << endl; } if (perr[0] >= 0) { while ((len=read(perr[0],str,1023))>0) { str[len] ='\0'; info += str; } close(perr[0]); kdDebug(5003) << "error-output from gpg: " << info << endl; } if(passphrase) close(ppass[0]); //printf("output = %s\n",output.data()); //printf("info = %s\n",info.data()); // we don't want a zombie, do we? ;-) rc = waitpid(0/*child_pid*/, &status, 0); if (rc==-1) printf("waitpid: %s\n", strerror(errno)); return OK; } QString KNPgpBase::addUserId() { QString cmd; if(!pgpUser.isEmpty()) { cmd += " -u \""; cmd += pgpUser; cmd += "\""; return cmd; } return ""; } void KNPgpBase::clear() { input = QString::null; output = QString::null; info = QString::null; errMsg = QString::null; signature = QString::null; signatureID = QString::null; recipients.clear(); status = OK; } void KNPgpBase::clearOutput() { output = QString::null; } QString KNPgpBase::lastErrorMessage() const { return errMsg; } // ------------------------------------------------------------------------- KNPgpBaseG::KNPgpBaseG() : KNPgpBase() { } KNPgpBaseG::~KNPgpBaseG() { } int KNPgpBaseG::encrypt(const QStrList *_recipients, bool /*ignoreUntrusted*/) { return encsign(_recipients, 0); } int KNPgpBaseG::sign(const char *passphrase) { return encsign(0, passphrase); } int KNPgpBaseG::encsign(const QStrList *_recipients, const char *passphrase, bool /*ignoreUntrusted*/) { QString cmd, pers; output = ""; kdDebug(5003) << "KNPgpBaseG::encsign" << endl; if(_recipients != 0) if(_recipients->count() <= 0) _recipients = 0; if(_recipients != 0 && passphrase != 0) cmd = "--batch --escape-from-lines --armor --always-trust --sign --encrypt "; else if( _recipients != 0 ) cmd = "--batch --escape-from-lines --armor --always-trust --encrypt "; else if(passphrase != 0 ) cmd = "--batch --escape-from-lines --armor --always-trust --clearsign "; else { kdDebug(5003) << "kpgpbase: Neither recipients nor passphrase specified." << endl; return OK; } if(passphrase != 0) cmd += addUserId(); if(_recipients != 0) { QStrListIterator it(*_recipients); while( (pers=it.current()) != 0 ) { cmd += " --recipient \""; cmd += pers; cmd += "\" "; ++it; } } if(flagEncryptToSelf) { cmd += " --recipient \""; cmd += user(); cmd += "\" "; } cmd += " --set-filename stdin "; kdDebug(5003) << "KNPgpBaseG::encsign runs gpg as: " << cmd << endl; status = runGpg(cmd.latin1(), passphrase); if(status == RUN_ERR) return status; if(_recipients != 0) { int index = 0; bool bad = FALSE; unsigned int num = 0; QString badkeys = ""; while((index = info.find("Cannot find the public key",index)) != -1) { bad = TRUE; index = info.find("'",index); int index2 = info.find("'",index+1); badkeys += info.mid(index, index2-index+1) + ", "; num++; } if(bad) { badkeys.stripWhiteSpace(); if(num == _recipients->count()) errMsg.sprintf("Could not find public keys matching the\n" "userid(s) %s.\n" "Message is not encrypted.\n", badkeys.latin1()); else errMsg.sprintf("Could not find public keys matching the\n" "userid(s) %s. These persons won't be able\n" "to read the message.", badkeys.latin1()); status |= MISSINGKEY; status |= ERROR; } } if(passphrase != 0) { if(info.find("Pass phrase is good") != -1) { //kdDebug() << "KNPgpBase: Good Passphrase!" << endl; status |= SIGNED; } if( info.find("bad passphrase") != -1) { errMsg = i18n("Bad pass Phrase; couldn't sign"); status |= BADPHRASE; status |= ERR_SIGNING; status |= ERROR; } } //kdDebug() << "status = " << status << endl; return status; } int KNPgpBaseG::decrypt(const char *passphrase) { QString cmd; int index, index2; output = ""; cmd = "--batch --set-filename stdin --decrypt "; status = runGpg(cmd.latin1(), passphrase); // pgp2.6 has sometimes problems with the ascii armor pgp5.0 produces // this hack can solve parts of the problem if(info.find("ASCII armor corrupted.") != -1) { kdDebug() << "removing ASCII armor header" << endl; int index1 = input.find("-----BEGIN PGP SIGNED MESSAGE-----"); if(index1 != -1) index1 = input.find("-----BEGIN PGP SIGNATURE-----", index1); else index1 = input.find("-----BEGIN PGP MESSAGE-----"); index1 = input.find("\n", index1); index2 = input.find("\n\n", index1); input.remove(index1, index2 - index1); status = runGpg(cmd.latin1(), passphrase); } if(status == RUN_ERR) { errMsg = i18n("error running gpg"); return status; } if( info.find("File contains key") != -1) { // FIXME: should do something with it... } if ((info.find("secret key not available") != -1) || ((info.find("key not found") != -1) && (info.find("Can't check signature") == -1))) { //kdDebug() << "kpgpbase: message is encrypted" << endl; status |= ENCRYPTED; if( info.find("bad passphrase") != -1) { if(passphrase != 0) { errMsg = i18n("Bad pass Phrase; couldn't decrypt"); kdDebug() << "KNPgpBase: passphrase is bad" << endl; status |= BADPHRASE; status |= ERROR; } } else { // no secret key fitting this message status |= NO_SEC_KEY; status |= ERROR; errMsg = i18n("Do not have the public key for this message"); kdDebug() << "KNPgpBase: no public key for this message" << endl; } // check for persons index = info.find("can only be read by:"); if(index != -1) { index = info.find("\n",index); int end = info.find("\n\n",index); recipients.clear(); while( (index2 = info.find("\n",index+1)) <= end ) { QString item = info.mid(index+1,index2-index-1); item.stripWhiteSpace(); recipients.append(item.latin1()); index = index2; } } } if((index = info.find("Signature made")) != -1) { //kdDebug() << "KNPgpBase: message is signed" << endl; status |= SIGNED; if ((info.find("Key matching expected") != -1) || (info.find("Can't check signature") != -1)) { index = info.find("key ID ",index); signatureID = info.mid(index+7,8); signature = i18n("unknown key ID ") + signatureID + " "; status |= UNKNOWN_SIG; status |= GOODSIG; } else if( info.find("Good signature") != -1 ) { status |= GOODSIG; // get signer index = info.find("\"",index); index2 = info.find("\"", index+1); signature = info.mid(index+1, index2-index-1); // get key ID of signer index = info.find("key ID ",index2); signatureID = info.mid(index+7,8); } else if( info.find("CRC error") != -1 ) { //kdDebug() << "BAD signature" << endl; status |= SIGNED; status |= ERROR; // get signer index = info.find("\"",index); index2 = info.find("\"", index+1); signature = info.mid(index+1, index2-index-1); // get key ID of signer index = info.find("key ID ",index2); signatureID = info.mid(index+7,8); } else if( info.find("Can't find the right public key") != -1 ) { status |= UNKNOWN_SIG; status |= GOODSIG; // this is a hack... - signature = i18n("??? (file ~/.gnupg/pubring.gpg not found)"); + signature = i18n("unknown (file ~/.gnupg/pubring.gpg not found)"); signatureID = "???"; } else { status |= ERROR; signature = ""; signatureID = ""; } } //kdDebug() << "status = " << status << endl; return status; } QStrList KNPgpBaseG::pubKeys() { QString cmd; int index, index2; cmd = "--batch --list-keys"; status = runGpg(cmd.latin1()); if(status == RUN_ERR) return 0; // now we need to parse the output QStrList publicKeys; index = output.find("\n",1)+1; // skip first to "\n" while( (index = output.find("\n",index)) != -1) { //parse line QString line; if( (index2 = output.find("\n",index+1)) != -1) { int index3 = output.find("pub ",index); int index4 = output.find("uid ",index); if ((index4 != -1) && ((index4 < index3) || (index3 == -1))) index3 = index4; if( (index3 count() <= 0) _recipients = 0; if(_recipients != 0 && passphrase != 0) cmd = "+batchmode +language=C -seat "; else if( _recipients != 0 ) cmd = "+batchmode +language=C -eat"; else if(passphrase != 0 ) cmd = "+batchmode +language=C -sat "; else { kdDebug(5003) << "kpgpbase: Neither recipients nor passphrase specified." << endl; return OK; } if(passphrase != 0) cmd += addUserId(); if(_recipients != 0) { QStrListIterator it(*_recipients); while( (pers=it.current()) != 0) { cmd += " \""; cmd += pers; cmd += "\""; ++it; } if(flagEncryptToSelf) cmd += " +EncryptToSelf"; } cmd += " -f"; status = run(cmd.latin1(), passphrase); if(status == RUN_ERR) return status; if(_recipients != 0) { int index = 0; bool bad = FALSE; unsigned int num = 0; QString badkeys = ""; if (info.find("Cannot find the public key") != -1) { index = 0; num = 0; while((index = info.find("Cannot find the public key",index)) != -1) { bad = TRUE; index = info.find("'",index); int index2 = info.find("'",index+1); if (num++) badkeys += ", "; badkeys += info.mid(index, index2-index+1); } if(bad) { badkeys.stripWhiteSpace(); if(num == _recipients->count()) errMsg.sprintf("Could not find public keys matching the\n" "userid(s) %s.\n" "Message is not encrypted.\n", badkeys.latin1()); else errMsg.sprintf("Could not find public keys matching the\n" "userid(s) %s. These persons won't be able\n" "to read the message.", badkeys.latin1()); status |= MISSINGKEY; status |= ERROR; } } if (info.find("skipping userid") != -1) { index = 0; num = 0; while((index = info.find("skipping userid",index)) != -1) { bad = TRUE; int index2 = info.find("\n",index+16); if (num++) badkeys += ", "; badkeys += info.mid(index+16, index2-index-16); index = index2; } if(bad) { badkeys.stripWhiteSpace(); if(num == _recipients->count()) errMsg.sprintf("Public keys not certified with trusted signature for\n" "userid(s) %s.\n" "Message is not encrypted.\n", badkeys.latin1()); else errMsg.sprintf("Public keys not certified with trusted signature for\n" "userid(s) %s. These persons won't be able\n" "to read the message.", badkeys.latin1()); status |= BADKEYS; status |= ERROR; } } } if(passphrase != 0) { if(info.find("Pass phrase is good") != -1) { //kdDebug() << "KNPgpBase: Good Passphrase!" << endl; status |= SIGNED; } if( info.find("Bad pass phrase") != -1) { errMsg = i18n("Bad pass Phrase; couldn't sign"); status |= BADPHRASE; status |= ERR_SIGNING; status |= ERROR; } } if (info.find("Encryption error") != -1) { errMsg = i18n("PGP error occured. Please check\nyour PGP setup and key rings."); status |= NO_SEC_KEY; status |= BADKEYS; status |= ERROR; } //kdDebug() << "status = " << status << endl; return status; } int KNPgpBase2::decrypt(const char *passphrase) { QString cmd; int index, index2; output = ""; cmd = "+batchmode +language=C -f"; status = run(cmd.latin1(), passphrase); // pgp2.6 has sometimes problems with the ascii armor pgp5.0 produces // this hack can solve parts of the problem if(info.find("ASCII armor corrupted.") != -1) { kdDebug() << "removing ASCII armor header" << endl; int index1 = input.find("-----BEGIN PGP SIGNED MESSAGE-----"); if(index1 != -1) index1 = input.find("-----BEGIN PGP SIGNATURE-----", index1); else index1 = input.find("-----BEGIN PGP MESSAGE-----"); index1 = input.find("\n", index1); index2 = input.find("\n\n", index1); input.remove(index1, index2 - index1); status = run(cmd, passphrase); } if(status == RUN_ERR) { errMsg = i18n("error running pgp"); return status; } if( info.find("File contains key") != -1) { // FIXME: should do something with it... } if(info.find("You do not have the secret key") != -1) { //kdDebug() << "kpgpbase: message is encrypted" << endl; status |= ENCRYPTED; if( info.find("Bad pass phrase") != -1) { if(passphrase != 0) { errMsg = i18n("Bad pass Phrase; couldn't decrypt"); kdDebug() << "KNPgpBase: passphrase is bad" << endl; status |= BADPHRASE; status |= ERROR; } } else { // no secret key fitting this message status |= NO_SEC_KEY; status |= ERROR; errMsg = i18n("Do not have the secret key for this message"); kdDebug() << "KNPgpBase: no secret key for this message" << endl; } // check for persons index = info.find("can only be read by:"); if(index != -1) { index = info.find("\n",index); int end = info.find("\n\n",index); recipients.clear(); while( (index2 = info.find("\n",index+1)) <= end ) { QString item = info.mid(index+1,index2-index-1); item.stripWhiteSpace(); recipients.append(item.latin1()); index = index2; } } } if((index = info.find("File has signature")) != -1) { //kdDebug() << "KNPgpBase: message is signed" << endl; status |= SIGNED; if( info.find("Key matching expected") != -1) { index = info.find("Key ID ",index); signatureID = info.mid(index+7,8); signature = i18n("unknown key ID ") + signatureID + " "; status |= UNKNOWN_SIG; status |= GOODSIG; } else if( info.find("Good signature") != -1 ) { status |= GOODSIG; // get signer index = info.find("\"",index); index2 = info.find("\"", index+1); signature = info.mid(index+1, index2-index-1); // get key ID of signer index = info.find("key ID ",index2); signatureID = info.mid(index+7,8); } else if( info.find("Can't find the right public key") != -1 ) { status |= UNKNOWN_SIG; status |= GOODSIG; // this is a hack... - signature = i18n("??? (file ~/.pgp/pubring.pgp not found)"); + signature = i18n("unknown (file ~/.pgp/pubring.pgp not found)"); signatureID = "???"; } else { status |= ERROR; signature = ""; signatureID = ""; } } //kdDebug() << "status = " << status << endl; return status; } QStrList KNPgpBase2::pubKeys() { QString cmd; int index, index2; cmd = "+batchmode +language=C -kv -f"; status = run(cmd); if(status == RUN_ERR) return 0; //truncate trailing "\n" if (output.length() > 1) output.truncate(output.length()-1); QStrList publicKeys; index = output.find("\n",1)+1; // skip first to "\n" while( (index = output.find("\n",index)) != -1) { //parse line QString line; if( (index2 = output.find("\n",index+1)) != -1) // skip last line { int index3 = output.find("pub ",index); if( (index3 >index2) || (index3 == -1) ) { // second adress for the same key line = output.mid(index+1,index2-index-1); line = line.stripWhiteSpace(); line = line.lower(); } else { // line with new key int index3 = output.find( QRegExp("/[0-9][0-9]/[0-9][0-9] "), index); line = output.mid(index3+7,index2-index3-7); line = line.lower(); } //kdDebug() << "KNPgpBase: found key for " << (const char *)line << endl; publicKeys.append(line.latin1()); } else break; index = index2; } return publicKeys; } int KNPgpBase2::signKey(const char *key, const char *passphrase) { QString cmd; cmd = "+batchmode +language=C -ks -f"; cmd += addUserId(); if(passphrase != 0) { QString aStr; aStr.sprintf(" \"-z%s\"",passphrase); cmd += aStr; } cmd += key; return run(cmd); } QString KNPgpBase2::getAsciiPublicKey(QString _person) { QString toexec; toexec.sprintf("+language=C -kxaf \"%s\"", _person.latin1()); status = run(toexec.latin1()); if(status == RUN_ERR) return QString::null; return output; } // ------------------------------------------------------------------------- KNPgpBase5::KNPgpBase5() : KNPgpBase() { } KNPgpBase5::~KNPgpBase5() { } int KNPgpBase5::encrypt(const QStrList *_recipients, bool ignoreUntrusted) { return encsign(_recipients, 0, ignoreUntrusted); } int KNPgpBase5::sign(const char *passphrase) { return encsign( 0, passphrase); } int KNPgpBase5::encsign(const QStrList *_recipients, const char *passphrase, bool ignoreUntrusted) { QString in,cmd,pers; int index; // used to work around a bug in pgp5. pgp5 treats files // with non ascii chars (umlauts, etc...) as binary files, but // we wan't a clear signature bool signonly = false; output = ""; if(_recipients != 0) if(_recipients->isEmpty()) _recipients = 0; if(_recipients != 0 && passphrase != 0) cmd = "-ats -f +batchmode=1"; else if( _recipients != 0 ) cmd = "-at -f +batchmode=1 "; else if(passphrase != 0 ) { cmd = "-bat -f +batchmode=1 "; signonly = true; } else { errMsg = "Neither recipients nor passphrase specified."; return OK; } if(ignoreUntrusted) cmd += " +NoBatchInvalidKeys=off"; if(passphrase != 0) cmd += addUserId(); if(_recipients != 0) { QStrListIterator it(*_recipients); while( (pers=it.current()) != 0) { cmd += " -r \""; cmd += pers; cmd += "\""; ++it; } if(flagEncryptToSelf) cmd += " +EncryptToSelf"; } if (signonly) { input.append("\n"); input.replace(QRegExp("[ \t]+\n"), "\n"); //strip trailing whitespace } //We have to do this otherwise it's all in vain status = run(cmd, passphrase); if(status == RUN_ERR) return status; // now parse the returned info if(info.find("Cannot unlock private key") != -1) { errMsg = i18n("The passphrase you entered is invalid."); status |= ERROR; status |= BADPHRASE; } if(!ignoreUntrusted) { QString aStr; index = -1; while((index = info.find("WARNING: The above key",index+1)) != -1) { int index2 = info.find("But you previously",index); int index3 = info.find("WARNING: The above key",index+1); if(index2 == -1 || (index2 > index3 && index3 != -1)) { // the key wasn't valid, no encryption to this person // extract the person index2 = info.find("\n",index); index3 = info.find("\n",index2+1); aStr += info.mid(index2+1, index3-index2-1); aStr += ", "; } } if(!aStr.isEmpty()) { aStr.truncate(aStr.length()-2); if(info.find("No valid keys found") != -1) errMsg = i18n("The key(s) you wan't to encrypt your message\n" "to are not trusted. No encryption done."); else errMsg = i18n("The following key(s) are not trusted:\n%1\n" "They will not be able to decrypt the message") .arg(aStr); status |= ERROR; status |= BADKEYS; } } if((index = info.find("No encryption keys found for")) != -1) { index = info.find(":",index); int index2 = info.find("\n",index); errMsg.sprintf("Missing encryption key(s) for: %s", info.mid(index,index2-index).latin1()); status |= ERROR; status |= MISSINGKEY; } if(signonly) output = "-----BEGIN PGP SIGNED MESSAGE-----\n\n" + input + "\n" + output; return status; } int KNPgpBase5::decrypt(const char *passphrase) { QString in = ""; output = ""; status = run("-f +batchmode=1", passphrase); if(status == RUN_ERR) return status; // lets parse the returned information. int index; index = info.find("Cannot decrypt message"); if(index != -1) { //kdDebug() << "message is encrypted" << endl; status |= ENCRYPTED; // ok. we have an encrypted message. Is the passphrase bad, // or do we not have the secret key? if(info.find("Need a pass phrase") != -1) { if(passphrase != 0) { errMsg = i18n("Bad pass Phrase; couldn't decrypt"); kdDebug() << "KNPgpBase: passphrase is bad" << endl; status |= BADPHRASE; status |= ERROR; } } else { // we don't have the secret key status |= NO_SEC_KEY; status |= ERROR; errMsg = i18n("Do not have the secret key for this message"); kdDebug() << "KNPgpBase: no secret key for this message" << endl; } // check for persons index = info.find("can only be decrypted by:"); if(index != -1) { index = info.find("\n",index); int end = info.find("\n\n",index); recipients.clear(); int index2; while( (index2 = info.find("\n",index+1)) <= end ) { QString item = info.mid(index+1,index2-index-1); item.stripWhiteSpace(); recipients.append(item.latin1()); index = index2; } } } index = info.find("Good signature"); if(index != -1) { //kdDebug() << "good signature" << endl; status |= SIGNED; status |= GOODSIG; // get key ID of signer index = info.find("Key ID "); int index2 = info.find(",",index); signatureID = info.mid(index+7,index2-index-8); // get signer index = info.find("\"",index); index2 = info.find("\"", index+1); signature = info.mid(index+1, index2-index-1); } index = info.find("BAD signature"); if(index != -1) { //kdDebug() << "BAD signature" << endl; status |= SIGNED; status |= ERROR; // get key ID of signer index = info.find("Key ID "); int index2 = info.find(",",index); signatureID = info.mid(index+7,index2-index-8); // get signer index = info.find("\"",index); index2 = info.find("\"", index+1); signature = info.mid(index+1, index2-index-1); } index = info.find("Signature by unknown key"); if(index != -1) { index = info.find("keyid: ",index); int index2 = info.find("\n",index); signatureID = info.mid(index+7,index2-index-7); signature = "unknown key ID " + signatureID + " "; // FIXME: not a very good solution... status |= SIGNED; status |= GOODSIG; } //kdDebug() << "status = " << status << endl; return status; } QStrList KNPgpBase5::pubKeys() { int index,index2; status = run("-l"); if(status == RUN_ERR) return 0; // now we need to parse the output QStrList publicKeys; index = output.find("\n",1)+1; // skip first to "\n" while( (index = output.find("\n",index)) != -1) { //parse line QString line; if( (index2 = output.find("\n",index+1)) != -1) { int index3 = output.find("uid ",index); if( (index3 1) info.truncate(info.length()-1); QStrList publicKeys; index = info.find("bits/keyID",1); // skip first to "\n" if (index ==-1) { index = info.find("Type bits",1); // skip first to "\n" if (index == -1) return 0; else compatibleMode = 0; } while( (index = info.find("\n",index)) != -1) { //parse line QString line; if( (index2 = info.find("\n",index+1)) != -1) // skip last line { int index3; if (compatibleMode) { int index_pub = info.find("pub ",index); int index_sec = info.find("sec ",index); if (index_pub < 0) index3 = index_sec; else if (index_sec < 0) index3 = index_pub; else index3 = (index_pub < index_sec ? index_pub : index_sec); } else { int index_rsa = info.find("RSA ",index); int index_dss = info.find("DSS ",index); if (index_rsa < 0) index3 = index_dss; else if (index_dss < 0) index3 = index_rsa; else index3 = (index_rsa < index_dss ? index_rsa : index_dss); } if( (index3 >index2) || (index3 == -1) ) { // second adress for the same key line = info.mid(index+1,index2-index-1); line = line.stripWhiteSpace(); line = line.lower(); } else { // line with new key int index4 = info.find( QRegExp("/[0-9][0-9]/[0-9][0-9] "), index); line = info.mid(index4+7,index2-index4-7); line = line.lower(); } //kdDebug() << "KNPgpBase: found key for " << (const char *)line << endl; publicKeys.append(line.latin1()); } else break; index = index2; } return publicKeys; } int KNPgpBase6::isVersion6() { QString cmd; QString empty; cmd = ""; status = run(cmd, empty.latin1()); if(status != OK) { errMsg = i18n("error running pgp"); return 0; } if( info.find("Version 6") != -1) { //kdDebug() << "kpgpbase: pgp version 6.x detected" << endl; return 1; } //kdDebug() << "kpgpbase: not pgp version 6.x" << endl; return 0; }